6 Stimmen

LINQ to SQL Paginierung und COUNT(*)

Ich verwende in meiner Webanwendung die Klasse PagedList, die vielen von Ihnen bekannt sein dürfte, wenn Sie sich mit ASP.NET MVC und LINQ to SQL beschäftigt haben. Sie wurde in einem Blog beschrieben von Rob Conery und eine ähnliche Inkarnation war in Dingen wie Nerd-Dinner , usw. Es funktioniert hervorragend, aber mein DBA hat Bedenken wegen möglicher künftiger Leistungsprobleme geäußert.

Sein Problem betrifft das SELECT COUNT(*), das als Ergebnis dieser Zeile ausgegeben wird:

TotalCount = source.Count();

Bei jeder Aktion, bei der Daten ausgelagert werden, wird eine zusätzliche Abfrage (wie unten) als Ergebnis des Aufrufs der Methode IQueryable.Count() ausgelöst:

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

Gibt es eine bessere Möglichkeit, dies zu handhaben? Ich erwog, die Count-Eigenschaft der PagedList-Klasse zu verwenden, um die Elementanzahl zu erhalten, aber erkannte, dass dies nicht funktionieren wird, weil es nur die Anzahl der Elemente zählt, die derzeit angezeigt werden (nicht die Gesamtzahl).

Wie stark wird die Leistung meiner Anwendung beeinträchtigt, wenn sich viele Daten in der Datenbank befinden?

7voto

Paul Creasey Punkte 27679

Iirc dieses Zeug ist ein Teil der Index-Statistiken und sollte sehr effizient sein, sollten Sie Ihren DBA bitten, seine Bedenken zu substatieren, anstatt voreilig zu optimieren.

2voto

Ronnie Punkte 21

Eigentlich ist dies ein ziemlich häufiges Problem mit Linq.

Ja, Indexstatistiken werden verwendet, wenn die Anweisung nur SELECT COUNT(*) AS [value] FROM [dbo].[Products] AS [t0] aber in 99 % der Fälle wird es auch WHERE-Anweisungen enthalten.

Es werden also grundsätzlich zwei SQL-Anweisungen ausgeführt:

  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

Sie erhalten Probleme, wenn die Tabelle häufig aktualisiert wird, da die COUNT(*) die in der ersten Anweisung zurückgegeben wird, nicht mit der zweiten Anweisung übereinstimmt, kann die Fehlermeldung "Zeile nicht gefunden oder geändert" ausgegeben werden.

1voto

davek Punkte 21771

Einige Datenbanken (Oracle, Postgresql, SQL Server, glaube ich) halten die Zeilenzahl in den Systemtabellen fest, obwohl diese manchmal nur bis zu dem Zeitpunkt genau sind, an dem die Statistiken zuletzt aktualisiert wurden (Oracle). Sie könnten diesen Ansatz verwenden, wenn Sie nur eine ziemlich genaue, aber nicht exakte Metrik benötigen.

Welche Datenbank verwenden Sie, oder gibt es da Unterschiede?

1voto

Garry Taylor Punkte 725

(PS: Ich weiß, dass Sie von MsSQL sprechen.)

Ich bin kein DBA, aber count(*) in MySQL ist ein echter Performance-Hit. Wenn man dies einfach in count(ID) ändert, wird die Geschwindigkeit wirklich verbessert.

Ich bin auf dieses Problem gestoßen, als ich eine Tabelle mit sehr großen GLOB (Bilder)-Daten abfragte. Das Abfragetool brauchte etwa 15 Sekunden zum Laden. Wenn ich die Abfrage auf count(id) änderte, konnte ich die Abfrage auf 0,02 reduzieren. Immer noch ein bisschen langsam, aber viel besser.

Ich glaube, das ist es, worauf der DBA hinaus will. Beim Debuggen von Linq habe ich festgestellt, dass die Anweisung, die zählt, sehr lange braucht (1 Sekunde), um zur nächsten Anweisung zu springen.

Nach meinen Erkenntnissen muss ich den Bedenken des DBA zustimmen...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X