DataTable.Select vs DataTable.rows.Find vs foreach vs Find (Предикат <T>)/Лямбда
У меня есть DataTable/collection, который кэшируется в памяти, я хочу использовать это как источник для генерации результатов для автоматического полного текстового поля (с использованием AJAX, конечно).
Я оцениваю различные варианты быстрого извлечения данных.
Количество элементов в коллекции/строках в datatable может варьироваться от 10000 до 2 000 000. (Чтобы мы не отвлекались, на данный момент предполагаем, что решение принято, у меня достаточно ОЗУ, и я буду использовать кэш, а не запрос базы данных для этого)
У меня есть дополнительная бизнес-логика для этой обработки; Я должен определить приоритет для автоматического полного списка в соответствии с столбцом priority
(int) в коллекции. Поэтому, если я кто-то ищет Micro
, и я получаю 20 результатов слов/предложений, начинающихся с Micro
, тогда я бы выбрал 10 лучших результирующих элементов с наивысшим приоритетом. (следовательно, необходимо иметь свойство приоритета, связанное со строковым значением).
Элементы коллекции уже отсортированы в алфавитном порядке.
Что было бы лучшим решением в этом случае.
1. Использование DataTable.Select(.
2. Использование DataTable.Rows.Find(.
3. используйте пользовательскую коллекцию с foreach или для повторения своих значений.
4. используйте общую коллекцию с анонимными делегатами или lambda (поскольку оба дают такую же производительность или не?)
Ответы
Ответ 1
Графики не размещены в моей записи в блоге; более подробную информацию можно найти на http://msdn.microsoft.com/en-us/library/dd364983.aspx
Еще одна вещь, которую я с тех пор обнаружил, заключается в том, что для больших наборов данных использование целочисленного родового словаря выполняет невероятно хорошо. Это также помогает устранить многие проблемы, вызванные операциями сортировки, необходимыми для операций агрегации, такими как min и max (либо с DataTable.Compute
, либо LINQ
).
В "закодированном родовом словаре" я подразумеваю Dictionary(Of String, Dictionary(Of String, Dictionary(Of Integer, List(Of DataRow))))
или подобный метод, где ключ для каждого словаря является поисковым термином.
Конечно, это не будет полезно при любых обстоятельствах, но у меня есть хотя бы один сценарий, в котором реализация этого подхода приводит к улучшению производительности 500x
.
В вашем случае я бы использовал простой словарь с первыми 1-5 символами, а затем List(Of String)
. Вам нужно будет создать этот словарь один раз, добавив слова в списки с первыми 1-5 символами, но после этого вы сможете получить невероятно быстрые результаты.
Обычно я обертываю такие вещи в классе, что позволяет мне делать такие вещи, как легко добавлять слова. Вы также можете использовать SortedList(Of String)
для автоматического сортировки результатов. Таким образом, вы можете быстро найти список слов, соответствующих первым N символам, которые были напечатаны.
Ответ 2
На моем autocomplete
, я сначала попытался использовать подход linq/lambda
, производительность немного медленная. DataTable.Select
быстрее, чем linq
, поэтому я использую это. Я еще не сравнил производительность между DataTable.Select
и datatable.Find
Ответ 3
Мы можем размышлять об этом весь день, но так как это не огромный фрагмент кода, почему бы не написать каждый из них и сравнить их друг с другом?
public delegate void TestProcedure();
public TimeSpan Benchmark(TestProcedure tp)
{
int testBatchSize = 5;
List<TimeSpan> results = new List<TimeSpan>();
for(int i = 0; i<testBatchSize; i++)
{
DateTime start = DateTime.Now;
tp();
results.Add(DateTime.Now - start);
}
return results.Min();
}
Ответ 4
согласно следующему блогу
http://blog.dotnetspeech.net/archive/2008/08/26/performance----datatable.select-vs-dictionary.aspx
DataTable.Rows.Find намного, намного быстрее, чем DataTable.Select.
Ответ 5
Как насчет DataView? Вы можете применить условие фильтрации и сортировать по приоритету и легко выполнить итерацию результатов, чтобы добавить к своим результатам.