it-swarm.com.de

SQL-Zählleistung (*)

Ich habe eine SQL-Tabelle BookChapters mit über 20 Millionen Zeilen. Es hat einen gruppierten Primärschlüssel (bookChapterID) und keine anderen Schlüssel oder Indizes. Die Ausführung der folgenden Abfrage dauert Millisekunden

if (select count(*) from BookChapters) = 0
...

Es dauert jedoch mehr als 10 Minuten, wenn ich es so ändere

if (select count(*) from BookChapters) = 1
...

oder

if (select count(*) from BookChapters) > 1
...

Warum das? Wie kann ich select count(*) schneller ausführen lassen?

35
danmiao

Mikael Eriksson hat eine gute Erklärung, warum die erste Abfrage schnell ist:

SQL Server optimiert es in: if exists(select * from BookChapters). Also wird nach einer Zeile gesucht, anstatt alle Zeilen in der Tabelle zu zählen.

Für die beiden anderen Abfragen würde SQL Server die folgende Regel verwenden. Um eine Abfrage wie SELECT COUNT(*) auszuführen, verwendet SQL Server den engsten nicht gruppierten Index, um die Zeilen zu zählen. Wenn die Tabelle keinen nicht gruppierten Index hat, muss sie die Tabelle durchsuchen.

Wenn Ihre Tabelle einen geclusterten Index hat, können Sie Ihre Zählung mit der folgenden Abfrage (von dieser Site ausgeliehen Get Row Counts) noch schneller abrufen Schnell! )

--SQL Server 2005/2008
SELECT OBJECT_NAME(i.id) [Table_Name], i.rowcnt [Row_Count]
FROM sys.sysindexes i WITH (NOLOCK)
WHERE i.indid in (0,1)
ORDER BY i.rowcnt desc

--SQL Server 2000
SELECT OBJECT_NAME(i.id) [Table_Name], i.rows [Row_Count]
FROM sysindexes i (NOLOCK)
WHERE i.indid in (0,1)
ORDER BY i.rows desc

Es wird die Systemtabelle sysindexes verwendet. Weitere Informationen finden Sie hier SQL Server 20 , SQL Server 2005 , SQL Server 2008 , SQL Server 2012

Hier ist ein weiterer Link Warum läuft mein SELECT COUNT (*) so langsam? mit einer anderen Lösung. Es zeigt Techniken, mit denen Microsoft die Anzahl der Zeilen schnell anzeigt, wenn Sie mit der rechten Maustaste auf die Tabelle klicken und Eigenschaften auswählen.

select sum (spart.rows)
from sys.partitions spart
where spart.object_id = object_id(’YourTable’)
and spart.index_id < 2

Sie sollten feststellen, dass dies sehr schnell zurückgibt, egal wie viele Tabellen Sie haben.

Wenn Sie noch SQL 2000 verwenden, können Sie die Nummer anhand der Tabelle sysindexes ermitteln.

select max(ROWS)
from sysindexes
where id = object_id(’YourTable’)

Diese Zahl kann geringfügig abweichen, abhängig davon, wie oft SQL die sysindexes-Tabelle aktualisiert, sie entspricht jedoch normalerweise (oder ist zumindest eng genug).

53

versuchen Sie dies, wenn Sie nur die Anzahl der Zeilen wissen möchten:

exec sp_spaceused [TABLE_NAME]
12
ehsandotnet

Wenn Sie sich die Ausführungspläne für Ihre Abfragen ansehen, werden Sie sehen, was los ist.

Ihre erste Abfrage if (select count(*) from BookChapters) = 0 wird vom Abfrageoptimierer als dieselbe wie if exists(select * from BookChapters) erkannt. SQL Server weiß, dass der Ausdruck wahr ist, wenn mindestens eine Zeile vorhanden ist, und sucht daher nach einer Zeile, anstatt alle Zeilen in der Tabelle zu zählen.

Bei Ihren anderen Abfragen kann es nicht so intelligent sein, und Sie müssen erst die Anzahl der Zeilen in der Tabelle zählen, bevor Sie entscheiden können, ob der Ausdruck als wahr oder falsch ausgewertet wird.

7
Mikael Eriksson

Haben Sie die Abfrage select count(BookChapterId) from BookChapterTable in Betracht gezogen? - wobei `BookChapterId ein nicht gruppierter Index ist. Das sollte es viel schneller laufen lassen.

Abhängig davon, wie die Tabelle verwendet wird und auf welche Zeilen zugegriffen wird, ist die Abfrage nach nicht gruppiertem Index möglicherweise der entscheidende Punkt: Ich habe nur einige Punkte von MDSN übernommen:

  • Bevor Sie nicht gruppierte Indizes erstellen, sollten Sie wissen, wie auf Ihre Daten zugegriffen wird. Erwägen Sie die Verwendung von nicht gruppierten Indizes für:
  • Spalten, die eine große Anzahl unterschiedlicher Werte enthalten, z. B. a
    Kombination aus Nachname und Vorname (wenn ein Clustered-Index für andere Spalten verwendet wird). Wenn es nur sehr wenige eindeutige Werte gibt, wie z
    nur 1 und 0, die meisten Abfragen verwenden den Index wegen einer Tabelle nicht
    Scan ist normalerweise effizienter.
  • Abfragen, die keine großen Ergebnismengen zurückgeben.
  • Spalten, die häufig an Suchbedingungen einer Abfrage beteiligt sind (WO
    Klausel), die exakte Übereinstimmungen zurückgibt.
  • Decision-Support-System-Anwendungen, für die häufig Verknüpfungen und Gruppierungen erforderlich sind. Erstellen Sie mehrere Nonclustered-Indizes für Spalten, die an Verknüpfungs- und Gruppierungsvorgängen beteiligt sind, und einen Clustered-Index für alle Fremdschlüsselspalten.
  • Deckt alle Spalten einer Tabelle in einer bestimmten Abfrage ab. Dadurch wird der Zugriff auf die Tabelle oder den Clustered-Index vollständig vermieden.
5
EL Yusubov

versuchen Sie Folgendes, wenn Sie feststellen müssen, ob die Tabelle mehr als eine Zeile enthält:

if (SELECT COUNT(*) FROM (SELECT TOP 2 * FROM BookChapters) AS b) > 1
2
WURMi