2010-05-14 3 views
27

Учитывая код ниже:DataView.RowFilter Vs DataTable.Select() против DataTable.Rows.Find()

Dataview someView = new DataView(sometable) 
someView.RowFilter = someFilter; 

if(someView.count > 0) { …. } 

целый ряд статей, которые говорят Datatable.Select() лучше, чем при использовании DataViews, но это до VS2008.

Solved: The Mystery of DataView's Poor Performance with Large Recordsets
Array of DataRecord vs. DataView: A Dramatic Difference in Performance

погуглить на эту тему я нашел некоторые статьи/темы форума, которые затрагивают Datatable.Select() само по себе является довольно багги (не уверен в этом) и невысока в различных сценариях.

Об этой теме (Best Practices ADO.NET) на msdn предлагается, чтобы при наличии первичного ключа, определенного в datatable, методы findrows() или find() должны использоваться insted of Datatable.Select().

Эта статья here (.NET 1.1) сравнивает все три подхода плюс еще пару. Но это для версии 1.1, поэтому не уверен, что они действительны еще сейчас. Accroding к этому DataRowCollection.Find() превосходит все подходы и Datatable.Select() превосходит DataView.RowFilter.

Так что я совершенно смущен тем, что может быть лучшим подходом к поиску строк в datatable. Или нет единого хорошего способа сделать это, в зависимости от сценария существуют несколько решений?

+0

Благодарим за вознаграждение! – thmshd

ответ

45

Вы ищете «лучший подход к поиску строк в datatable», поэтому мне сначала нужно спросить: «лучше» для чего? Я думаю, что у любой техники есть сценарии, где она может быть лучше других.

Во-первых, давайте посмотрим на DataView.RowFilter: DataView имеет некоторые преимущества в привязке данных. Его очень ориентированный взгляд, поэтому он обладает мощными функциями сортировки, фильтрации или поиска, но создает некоторые накладные расходы и не оптимизирован для производительности. Я бы выбрал DataView.RowFilter для небольших наборов записей и/или где вы воспользуетесь другими функциями (например, прямой привязкой данных к представлению).

Большинство фактов о DataView, которые вы можете прочитать в старых сообщениях, по-прежнему применяются.

Во-вторых, вы должны предпочесть DataTable.Rows.Find над DataTable.Select, если хотите всего лишь одного попадания. Зачем? DataTable.Rows.Find возвращает только одну строку. По сути, когда вы указываете первичный ключ, создается двоичное дерево. У этого есть некоторые накладные расходы, связанные с ним, но значительно ускоряет поиск.

DataTable.Select работает медленнее, но может пригодиться, если у вас есть несколько критериев и не заботятся об индексированных или неиндексированных строках: он может найти в основном все, но не оптимизирован для производительности. По существу, DataTable.Select должен пройти всю таблицу и сравнить каждую запись по критериям, которые вы прошли.

Надеюсь, вы найдете этот небольшой обзор полезным.

Предлагаю взглянуть на this article, это было полезно для меня касательно вопросов производительности. Этот пост содержит некоторые цитаты из него.

Немного UPDATE: Кстати, это может показаться немного выходит за рамки вашего вопроса, но почти всегда самым быстрым решением, чтобы сделать фильтрацию и поиск на внутреннем интерфейсе.Если вы хотите простоту и имеете SQL Server в качестве backend и .NET3 + на клиенте, перейдите на LINQ-to-SQL. Поиск объектов Linq очень удобен и создает запросы, которые выполняются на стороне сервера. Хотя LINQ-to-Objects также очень удобная, но и более медленная. В случае, если вы не знаете, уже ....

+0

Я только что нашел случай, когда результаты были разными между методами .Select и RowFilter. В моем случае Select возвратил 532 строки, а RowFilter возвращал 540. Я обнаружил, что разница связана с дополнительными пробелами в данных таблицы и разрешена с помощью Trim в заявлении select TRIM (VendorNumber) = '500' – James

20

пост Thomashaid подводит его красиво:

  • DataView.RowFilter для связывания.
  • DataTable.Rows.Find предназначено для поиска по первичному ключу только.
  • DataTable.Select предназначен для поиска по нескольким столбцам, а также для определения порядка.

Избегайте создания многих элементов DataView в цикле и использования их RowFilters для поиска записей. Это резко снизит производительность.

Я хотел бы добавить, что DataTable.Select может использовать индексы. Вы можете создать индекс на DataTable, создавая DataView и указав порядок сортировки:

DataView dv = new DataView(dt); 
dv.Sort = "Col1, Col2"; 

Затем, когда вы звоните DataTable.Select(), он может использовать этот индекс при выполнении запроса. Мы использовали этот метод для серьезного повышения производительности в тех местах, где мы используем один и тот же запрос много раз. (Обратите внимание, что это было до того, как Linq существовал.)

Трюк заключается в правильном определении порядка сортировки для оператора Select. Поэтому, если ваш запрос «Col1 = 1 и Col2 = 4», тогда вам понадобится «Col1, Col2», как в приведенном выше примере.

Обратите внимание, что создание индекса может зависеть от фактических вызовов для создания DataView. Нам пришлось использовать конструктор new DataView(DataTable dt), а затем указать свойство Sort на отдельном шаге. Поведение может немного измениться с разными версиями .NET.

+1

Whoa this is супер удобный. Я не могу поверить, что это не документировано в MSDN. С 1 строкой кода я резко улучшил производительность своих вызовов DataTable.Select(), не выполняя все глупые FindRows() и работу Dictionary. THANKS –

+1

супер, это сделал мой день. Теперь запросы на 300% быстрее! – JohanLarsson

+1

Если вы пройдете через основной источник .Net, вы увидите, что часто .Select() создает сам индекс, если условия правильные. Например, когда используется простое выражение типа «col1 = 3 и col2 = 4». Это можно увидеть, просмотрев приватное поле [indexes] таблицы после выбора. В этих случаях нет необходимости создавать DataView. Ответ выше также не работает для меня, мне нужно создать DataView с помощью только конструктора таблицы, а затем установить свойство [Sort] отдельно. Не знаю, почему ... – LMK

Смежные вопросы