在內存中的 List<T>
上使用 LINQ 查詢時,加索引并不像數據庫那樣有內置支持,但可以通過以下方式提高查詢性能:
1. 手動構建索引
可以手動構建一個字典 (Dictionary<TKey, TValue>
),將需要查詢的字段作為鍵,值為對應的數據。查詢時直接利用字典的 O(1) 查找性能。
示例代碼:
// 假設有一個類
public class Employee
{public int Id { get; set; }public string Name { get; set; }
}// 構建索引
var employees = new List<Employee>
{new Employee { Id = 1, Name = "Alice" },new Employee { Id = 2, Name = "Bob" },new Employee { Id = 3, Name = "Charlie" }
};// 創建索引
var employeeIndex = employees.ToDictionary(e => e.Id, e => e);// 查詢時使用索引
int searchId = 2;
if (employeeIndex.TryGetValue(searchId, out var employee))
{Console.WriteLine($"Found: {employee.Name}");
}
else
{Console.WriteLine("Not Found");
}
2. 預先分組以提高查詢性能
對于需要多次按某個字段查詢的場景,可以使用 Lookup<TKey, TElement>
預分組數據。Lookup
類似于 Dictionary
,但支持一個鍵對應多個值。
示例代碼:
// 構建分組索引
var employeeLookup = employees.ToLookup(e => e.Name);// 按 Name 查詢
string searchName = "Alice";
foreach (var emp in employeeLookup[searchName])
{Console.WriteLine($"Found: {emp.Name} with Id: {emp.Id}");
}
3. 自定義數據結構
如果查詢條件多樣化,可以構建多字段索引,類似于復合索引。
示例代碼:
// 復合索引
var compositeIndex = employees.ToDictionary(e => (e.Id, e.Name), e => e);// 查詢
var key = (Id: 1, Name: "Alice");
if (compositeIndex.TryGetValue(key, out var result))
{Console.WriteLine($"Found: {result.Name}");
}
4. 排序后使用二分查找
如果 List<T>
是按查詢字段排序的,可以使用 BinarySearch
來快速查找。
示例代碼:
// 排序列表
employees = employees.OrderBy(e => e.Id).ToList();// 二分查找
int searchId = 2;
var found = employees.BinarySearch(new Employee { Id = searchId },Comparer<Employee>.Create((x, y) => x.Id.CompareTo(y.Id))
);if (found >= 0)
{Console.WriteLine($"Found: {employees[found].Name}");
}
else
{Console.WriteLine("Not Found");
}
5. 使用緩存優化查詢
如果查詢是頻繁且集中在某些字段上,可以構建一個緩存層,例如使用 MemoryCache
。
示例代碼:
using System.Runtime.Caching;// 創建緩存
var cache = MemoryCache.Default;
string cacheKey = "EmployeeById";
cache[cacheKey] = employeeIndex; // 使用之前構建的字典// 查詢緩存
if (cache.Contains(cacheKey))
{var cachedIndex = (Dictionary<int, Employee>)cache[cacheKey];if (cachedIndex.TryGetValue(2, out var cachedEmployee)){Console.WriteLine($"From Cache: {cachedEmployee.Name}");}
}
6. 結合并行查詢
對于大規模數據,可以結合并行 LINQ (PLINQ) 提高查詢速度。
示例代碼:
// 使用 PLINQ
var result = employees.AsParallel().Where(e => e.Name.StartsWith("A")).ToList();foreach (var emp in result)
{Console.WriteLine($"Found: {emp.Name}");
}
總結
加索引的方法需要根據具體場景選擇:
- 如果查詢頻繁,使用
Dictionary
或Lookup
。 - 如果是多字段組合查詢,構建復合索引。
- 如果數據較多且一次性查詢,考慮使用排序加二分查找。
- 對于性能要求極高的場景,可以結合緩存或并行查詢優化。
根據你的需求,可以選用其中一個或多個組合方式。