.Net 4.5 и проблема все еще там.
Вот результаты простого теста, в котором DataTable.Select и различные реализации словаря сравниваются по времени ЦП (результаты в миллисекундах).
#Rows Table.Select Hashtable[] SortedList[] Dictionary[]
1000 43,31 0,01 0,06 0,00
6000 291,73 0,07 0,13 0,01
11000 604,79 0,04 0,16 0,02
16000 914,04 0,05 0,19 0,02
21000 1279,67 0,05 0,19 0,02
26000 1501,90 0,05 0,17 0,02
31000 1738,31 0,07 0,20 0,03
Проблема:
Метод DataTable.Select внутренне создает экземпляр класса System.Data.Select, а этот класс «Выбор» создает индексы на основе полей (столбцов), указанных в запросе. Класс Select повторно использует созданные им индексы, но реализация DataTable не использует экземпляр класса Select повторно, поэтому индексы создаются заново каждый раз, когда вызывается DataTable.Select. (Такое поведение можно наблюдать декомпиляцией System.Data)
Решение:
Предположим, следующий запрос
DataRow[] rows = data.Select("COL1 = 'VAL1' AND (COL2 = 'VAL2' OR COL2 IS NULL)");
Вместо этого создайте и заполните словарь с ключами, соответствующими различным комбинациям значений значений столбцов, используемых в качестве фильтра. (Эта относительно дорогая операция должна быть выполнена только один раз, и экземпляр словаря должен быть использован повторно)
Dictionary<string, List<DataRow>> di = new Dictionary<string, List<DataRow>>();
foreach (DataRow dr in data.Rows)
{
string key = (dr["COL1"] == DBNull.Value ? "<NULL>" : dr["COL1"]) + "//" + (dr["COL2"] == DBNull.Value ? "<NULL>" : dr["COL2"]);
if (di.ContainsKey(key))
{
di[key].Add(dr);
}
else
{
di.Add(key, new List<DataRow>());
di[key].Add(dr);
}
}
Запрос словаря (может потребоваться несколько запросов) для фильтрации строк и объединения результатов в список
string key1 = "VAL1//VAL2";
string key2 = "VAL1//<NULL>";
List<DataRow>() results = new List<DataRow>();
if (di.ContainsKey(key1))
{
results.AddRange(di[key1]);
}
if (di.ContainsKey(key2))
{
results.AddRange(di[key2]);
}