LINQ to SQL Pagination и COUNT (*)

Я использую класс PagedList в своем веб-приложении, с которым многие из вас могут быть знакомы, если вы что-то делали с ASP.NET MVC и LINQ to SQL. Об этом писал в блоге Роб Конери и подобное воплощение было включено в такие вещи, как Nerd Dinner и т. д. Это отлично работает, но мой Администратор базы данных выразил обеспокоенность по поводу потенциальных проблем с производительностью в будущем.

Его проблема связана с SELECT COUNT (*), который выдается в результате этой строки:

TotalCount = source.Count();

Любое действие с выгруженными данными вызовет дополнительный запрос (как показано ниже) в результате вызова метода IQueryable.Count ():

SELECT COUNT(*) AS [value] FROM [dbo].[Products] AS [t0] 

Есть ли лучший способ справиться с этим? Я рассматривал возможность использования свойства Count класса PagedList для получения количества элементов, но понял, что это не сработает, потому что он подсчитывает только количество элементов, отображаемых в данный момент (а не общее количество).

Насколько сильно снизится производительность моего приложения при большом количестве данных в базе данных?


person Ryan Rivest    schedule 12.02.2010    source источник


Ответы (4)


iirc этот материал является частью статистики индекса и должен быть очень эффективным, вам следует попросить администратора базы данных обосновать свои опасения, а не проводить преждевременную оптимизацию.

person Paul Creasey    schedule 12.02.2010
comment
Проголосовали так сильно, что сломали интернет. ;) Если дополнительный счетчик запросов снизит производительность вашей базы данных, у вас возникнут серьезные проблемы. - person John Farrell; 13.02.2010

На самом деле это довольно распространенная проблема с Linq.

Да, статистика индекса будет использоваться, если оператор был только SELECT COUNT(*) AS [value] FROM [dbo].[Products] AS [t0], но в 99% случаев он также будет содержать операторы WHERE.

Таким образом, в основном выполняются два оператора SQL:

  1. SELECT COUNT(*) AS [value] FROM [dbo].[Products] AS [t0] WHERE blah=blah and someint=500

  2. SELECT blah, someint FROM [dbo].[Products] AS [t0] WHERE blah=blah and someint=500

Вы начинаете получать проблемы, если таблица часто обновляется, поскольку COUNT(*), возвращаемый в первом операторе, не совпадает со вторым оператором ... это может вернуть сообщение об ошибке «Строка не найдена или не изменена».

person Ronnie    schedule 14.10.2010

Некоторые базы данных (думаю, Oracle, Postgresql, SQL Server) ведут учет количества строк в системных таблицах; хотя иногда они точны только до момента последнего обновления статистики (Oracle). Вы можете использовать этот подход, если вам нужна только довольно точная, но не точная метрика.

Какую базу данных вы используете или это варьируется?

person davek    schedule 12.02.2010

(PS Я знаю, что вы, однако, говорите о MsSQL)

Я не администратор баз данных, но count (*) в MySQL сильно снижает производительность. Простое изменение этого параметра на count (ID) действительно улучшает скорость.

Я столкнулся с этим, когда запрашивал таблицу с очень большими данными GLOB (изображения). Средство запроса загружается примерно через 15 секунд. Изменение запроса на count (id) уменьшило запрос до 0,02. Все еще немного медленнее, но намного лучше.

Я думаю, это то, к чему стремится администратор базы данных. Тогда я заметил, что при отладке Linq подсчитывающему оператору требуется очень много времени (1 секунда), чтобы перейти к следующему оператору.

Основываясь на своих выводах, я должен согласиться с утверждениями администратора базы данных ...

person Garry Taylor    schedule 12.01.2012