Подсчет первичного ключа в LINQ очень медленный - PullRequest
1 голос
/ 14 мая 2009

Я думал, что LINQ to SQL настроен на производительность?

Следующий LINQ to SQL для подсчета очень плохой

Dim uniqueFactors As Integer = db.LargeTable.Distinct.Count

производит:

SELECT COUNT(*) AS [value]
FROM [dbo].[LargeTable] AS [t0]
WHERE ([t0].[ID] % @p0) = @p1

Как каждый самый быстрый способ подсчета количества записей на основе первичного ключа равен

SELECT  @totalRowCount = rows
FROM    sysindexes
WHERE   id = OBJECT_ID('LargeTable')
    AND indid < 2

Итак, вопрос, как я могу гарантировать, что LINQ to SQL быстро выполнит подсчет при запросе Count (*)?

Ответы [ 5 ]

2 голосов
/ 14 мая 2009

Ну, это зависит от того, что вы ожидаете. Если вы запрашиваете «Distinct.Count» на столе, вы указываете LINQ делать именно то, что он делает. Так как это приведет к сканированию таблицы, для больших таблиц это будет медленно.

SELECT COUNT (*) - это единственный способ, которым SQL Server (и, следовательно, LINQ) может дать вам точное, актуальное количество строк в таблице.

Выбор строк из sysindexes (или предпочтительно: sys.partitions в SQL Server 2005 и более поздних версиях - представления "sysindexes" устарели) даст вам приблизительное число - но это не гарантируется абсолютно правильно и актуально.

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

Марк

1 голос
/ 21 марта 2013

У меня была какая-то похожая проблема, я попробовал это и получилось лучше:

child.count (x => x.paretnID == inputParentID) child.where (x => x.parentID == inputParentID)

мой оригинальный код, который занимал около 15-20 секунд на каждой итерации, был: return (isEdit)? db.ChasisBuys.Single (x => x.ChasisBuyID == long.Parse (Request.QueryString ["chbid"])). Chasises.Count (y => y.Bikes.Count> 0 && y.ColorID == buyItems [(int) index] .ColorID && y.ChasisTypeID == buyItems [(int) index] .ChasisTypeID) .ToString (): "-";

новый код, который работает хорошо:

    **return (isEdit) ? db.Chasises.Where(x => x.ChasisBuyID == long.Parse(Request.QueryString["chbid"])).Count(y => y.Bikes.Count > 0 && y.ColorID == buyItems[(int)index].ColorID && y.ChasisTypeID == buyItems[(int)index].ChasisTypeID).ToString() : "-";**

База данных насчитывает около 1000 записей в шасси, около 5 в chasisBuys и около 20 в байках. Мое мнение таково, что запросы Linq to SQL не выполняют предварительных оценок, таких как логические выражения, которые, например, если вы напишите «return a && b && c;» если утверждение a является ложным, другие операторы не оцениваются, и я ожидал такого в linq to sql, но это не так.

0 голосов
/ 13 сентября 2011

Если вы ищете простой COUNT, который все, что я хотел, и не хотите ждать вечно, не используйте методы Entity.

Используйте простой формат LINQ to SQL.

int largeCount = (from o in db.LargeTable
                       where o.SomeField == somVal
                       select o).Count();
0 голосов
/ 14 мая 2009

Изменение вашего linq на "db.LargeTable. Distinct. Count ();"

Должен выдать следующий SQL

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

Который должен использовать сканирование индекса вместо сканирования таблицы. Который должен быть намного быстрее.

0 голосов
/ 14 мая 2009

Я не могу воспроизвести ваш TSQL; Вы пропустили часть вопроса LINQ (то есть "где") из вопроса? Независимо от того, как я стараюсь, я получаю довольно нормальный TSQL, который работает хорошо ...

Поскольку первичный ключ уникален, почему бы не просто:

int count = db.LargeTable.Count();

В противном случае; Вы пробовали выбрать первичный ключ?

int count = db.LargeTable.Select(x=>x.Id).Distinct().Count();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...