Ich bin auf Artikel gestoßen, die besagen, dass SELECT COUNT(*) FROM TABLE_NAME
sie langsam sind, wenn die Tabelle viele Zeilen und viele Spalten enthält.
Ich habe eine Tabelle, die vielleicht sogar Milliarden von Zeilen enthält [sie hat ungefähr 15 Spalten]. Gibt es eine bessere Möglichkeit, die GENAUE Anzahl der Zeilen einer Tabelle zu ermitteln?
Bitte beachten Sie vor Ihrer Antwort Folgendes:
Ich suche eine datenbankunabhängige Lösung. Es ist in Ordnung, wenn es MySQL , Oracle , MS SQL Server abdeckt . Aber wenn es wirklich keine datenbankanbieterunabhängige Lösung gibt, werde ich mich mit unterschiedlichen Lösungen für unterschiedliche Datenbankanbieter zufrieden geben.
Ich kann dazu kein anderes externes Tool verwenden. Ich suche hauptsächlich eine SQL-basierte Lösung.
Ich kann mein Datenbankdesign nicht weiter normalisieren. Es ist bereits in 3NF und außerdem wurde bereits viel Code darum geschrieben.
Antworten:
Einfache Antwort:
COUNT(*)
Anmerkungen:
COUNT (1) = COUNT (*) = COUNT (PrimaryKey) für alle Fälle
Bearbeiten:
SQL Server-Beispiel (1,4 Milliarden Zeilen, 12 Spalten)
1 Läufe, 5:46 Minuten, Anzahl = 1.401.659.700
2 Läufe, beide unter 1 Sekunde, zählen = 1.401.659.670
Der zweite hat weniger Zeilen = falsch. Wäre je nach Schreibvorgang gleich oder höher (Löschvorgänge werden hier außerhalb der Geschäftszeiten ausgeführt)
quelle
COUNT(*) = COUNT(key)
. Das ist einfach falsch. Wenn es keineNOT NULL
Einschränkung gibt, können sie nicht gleich sein (sowohl in den Ergebnissen als auch im Ausführungsplan).index_id < 2
?Der mit Abstand schnellste Weg unter MySQL ist:
Sie erhalten sofort alle Ihre Tabellen mit der Zeilenanzahl (das ist die Summe) zusammen mit vielen zusätzlichen Informationen, wenn Sie möchten.
quelle
Das hängt von der Datenbank ab. Einige Beschleunigungen zählen, indem beispielsweise verfolgt wird, ob Zeilen im Index aktiv oder tot sind, sodass ein Index-Scan nur die Anzahl der Zeilen extrahieren kann. Andere tun dies nicht und erfordern daher den Besuch der gesamten Tabelle und das Zählen der Live-Zeilen nacheinander. Beides wird für einen riesigen Tisch langsam sein.
Beachten Sie, dass Sie im Allgemeinen eine gute Schätzung mithilfe von Abfrageoptimierungstools, Tabellenstatistiken usw. extrahieren können. Im Fall von PostgreSQL können Sie beispielsweise die Ausgabe von analysieren
explain count(*) from yourtable
und eine einigermaßen gute Schätzung der Anzahl der Zeilen erhalten. Was mich zu Ihrer zweiten Frage bringt.Ernsthaft? :-) Du meinst wirklich die genaue Anzahl aus einer Tabelle mit Milliarden von Zeilen? Bist du dir wirklich sicher? :-)
Wenn Sie dies wirklich tun, können Sie mithilfe von Triggern eine Spur der Gesamtsumme verfolgen. Beachten Sie jedoch die Parallelität und Deadlocks, wenn Sie dies tun.
quelle
Um Ihre Frage einfach zu beantworten: Nein .
Wenn Sie dazu einen DBMS-unabhängigen Weg benötigen, ist der schnellste Weg immer:
Einige DBMS-Anbieter haben möglicherweise schnellere Möglichkeiten, die nur für ihre Systeme funktionieren. Einige dieser Optionen sind bereits in anderen Antworten enthalten.
COUNT(*)
sollte ohnehin vom DBMS optimiert werden (zumindest von jedem PROD-würdigen DB), versuchen Sie also nicht, deren Optimierungen zu umgehen.Nebenbei bemerkt:
Ich bin sicher, dass viele Ihrer anderen Abfragen aufgrund Ihrer Tabellengröße ebenfalls lange dauern. Alle Leistungsprobleme sollten wahrscheinlich behoben werden, indem Sie schnell über Ihr Schemadesign nachdenken. Mir ist klar, dass Sie gesagt haben, dass es keine Option zum Ändern ist, aber es könnte sich herausstellen, dass Abfragen von mehr als 10 Minuten auch keine Option sind. 3. NF ist nicht immer der beste Ansatz , wenn Sie Geschwindigkeit benötigen, und manchmal können Daten in mehreren Tabellen aufgeteilt werden , wenn die Datensätze nicht haben , um zusammen gelagert werden. Etwas zum Nachdenken...
quelle
Ich habe dieses Skript von einer anderen StackOverflow-Frage / Antwort erhalten:
Mein Tisch hat 500 Millionen Datensätze und die oben genannten Ergebnisse werden in weniger als 1 ms zurückgegeben. Inzwischen,
dauert volle 39 Minuten, 52 Sekunden!
Sie ergeben genau die gleiche Anzahl von Zeilen (in meinem Fall genau 519326012).
Ich weiß nicht, ob das immer der Fall wäre.
quelle
Sie können dies versuchen sp_spaceused (Transact-SQL)
quelle
Wenn die SQL Server-Edition 2005/2008 ist, können Sie DMVs verwenden, um die Zeilenanzahl in einer Tabelle zu berechnen:
Für das SQL Server 2000-Datenbankmodul funktionieren sysindexes. Es wird jedoch dringend empfohlen, die Verwendung in zukünftigen Editionen von SQL Server zu vermeiden, da diese möglicherweise in naher Zukunft entfernt werden.
Beispielcode aus: So erhalten Sie schnell und schmerzlos Tabellenzeilenzählungen
quelle
ich benutze
quelle
Ich bin bei weitem nicht so kompetent wie andere, die geantwortet haben, aber ich hatte ein Problem mit einem Verfahren, mit dem ich eine zufällige Zeile aus einer Tabelle ausgewählt habe (nicht übermäßig relevant), aber ich musste die Anzahl der Zeilen in meiner Referenztabelle kennen um den Zufallsindex zu berechnen. Bei Verwendung der herkömmlichen Funktion Count (*) oder Count (1) wurden gelegentlich bis zu 2 Sekunden benötigt, damit meine Abfrage ausgeführt werden konnte. Also benutze ich stattdessen (für meine Tabelle mit dem Namen 'tbl_HighOrder'):
Es funktioniert hervorragend und die Abfragezeiten in Management Studio sind Null.
quelle
Nun, spät um 5 Jahre und unsicher, ob es hilft:
Ich habe versucht, die Nr. Zu zählen. von Zeilen in einer SQL Server-Tabelle mit MS SQL Server Management Studio und einem Überlauffehler, dann habe ich Folgendes verwendet:
Wählen Sie count_big (1) FROM [Datenbankname]. [Datenbank]. [FactSampleValue];
Das Ergebnis :
24296650578 Zeilen
quelle
Ich habe diesen guten Artikel gefunden. SQL Server - HOW-TO: Ruft schnell die genaue Zeilenanzahl für die Tabelle ab, aus
martijnh1
der eine gute Zusammenfassung für jedes Szenario hervorgeht.Ich muss dies erweitern, wo ich eine Zählung basierend auf einer bestimmten Bedingung bereitstellen muss, und wenn ich diesen Teil herausfinde, werde ich diese Antwort weiter aktualisieren.
In der Zwischenzeit hier die Details aus dem Artikel:
Methode 1:
Abfrage:
Bemerkungen:
Führt einen vollständigen Tabellenscan durch. Langsam auf großen Tischen.
Methode 2:
Abfrage:
Bemerkungen:
Schneller Weg zum Abrufen der Zeilenanzahl. Hängt von Statistiken ab und ist ungenau.
Führen Sie DBCC UPDATEUSAGE (Database) WITH COUNT_ROWS aus, was bei großen Tabellen viel Zeit in Anspruch nehmen kann.
Methode 3:
Abfrage:
Bemerkungen:
Die Art und Weise, wie das SQL Management Studio Zeilen zählt (siehe Tabelleneigenschaften, Speicher, Zeilenanzahl). Sehr schnell, aber immer noch eine ungefähre Anzahl von Zeilen.
Methode 4:
Abfrage:
Bemerkungen:
Schneller (wenn auch nicht so schneller wie Methode 2) Betrieb und ebenso wichtig, zuverlässig.
quelle
Ich glaube nicht, dass es eine allgemeine, immer schnellste Lösung gibt: Einige RDBMS / Versionen haben eine spezielle Optimierung
SELECT COUNT(*)
, die schnellere Optionen verwendet, während andere einfach Tabellen scannen. Sie müssten für den zweiten Satz zu den Dokumentations- / Support-Sites gehen, für die wahrscheinlich eine spezifischere Abfrage geschrieben werden muss, normalerweise eine, die auf irgendeine Weise auf einen Index trifft.BEARBEITEN:
Hier ist ein Gedanke, der je nach Schema und Verteilung der Daten funktionieren könnte: Haben Sie eine indizierte Spalte, die beispielsweise auf einen zunehmenden Wert, eine numerisch zunehmende ID oder sogar einen Zeitstempel oder ein Datum verweist? Unter der Annahme, dass keine Löschvorgänge stattfinden, sollte es dann möglich sein, die Anzahl bis zu einem aktuellen Wert (gestriges Datum, höchster ID-Wert an einem aktuellen Stichprobenpunkt) zu speichern und die Anzahl darüber hinaus hinzuzufügen, was sich sehr schnell im Index auflösen sollte . Natürlich sehr abhängig von Werten und Indizes, aber für so ziemlich jede Version eines DBMS anwendbar.
quelle
SELECT COUNT(*)
. Sogar MySQL macht es anscheinend ....Ich komme zu spät zu dieser Frage, aber hier ist, was Sie mit MySQL tun können (da ich MySQL verwende). Ich teile meine Beobachtungen hier:
Ergebnis Zeilenanzahl
: 508534
Konsolenausgabe: Betroffene Zeilen: 0 Gefundene Zeilen: 1 Warnungen: 0 Dauer für 1 Abfrage: 0,125 Sek.
Es dauert eine Weile für eine Tabelle mit einer großen Anzahl von Zeilen, aber die Zeilenanzahl ist sehr genau.
Ergebnis Zeilenanzahl
: 511235
Konsolenausgabe: Betroffene Zeilen: 0 Gefundene Zeilen: 1 Warnungen: 0 Dauer für 1 Abfrage: 0,250 Sek. Zusammenfassung: Die Zeilenanzahl ist nicht genau.
Ergebnis Zeilenanzahl
: 507806
Konsolenausgabe: Betroffene Zeilen: 0 Gefundene Zeilen: 48 Warnungen: 0 Dauer für 1 Abfrage: 1.701 Sek.
Die Zeilenanzahl ist nicht genau.
Ich bin kein MySQL- oder Datenbankexperte, aber ich habe festgestellt, dass Sie für sehr große Tabellen Option 2 oder 3 verwenden können, um eine „faire Vorstellung“ davon zu erhalten, wie viele Zeilen vorhanden sind.
Ich musste diese Zeilenzahlen abrufen, um einige Statistiken auf der Benutzeroberfläche anzuzeigen. Bei den oben genannten Abfragen wusste ich, dass die Gesamtzahl der Zeilen mehr als 500.000 betrug. Daher habe ich Statistiken wie "Mehr als 500.000 Zeilen" angezeigt, ohne die genaue Anzahl der Zeilen anzuzeigen.
Vielleicht habe ich die Frage des OP nicht wirklich beantwortet, aber ich teile mit, was ich in einer Situation getan habe, in der solche Statistiken benötigt wurden. In meinem Fall war es akzeptabel, die ungefähren Zeilen anzuzeigen, und so funktionierte das Obige für mich.
quelle
Nicht gerade eine DBMS-unabhängige Lösung, aber zumindest Ihr Client-Code wird den Unterschied nicht erkennen ...
Erstellen Sie eine weitere Tabelle T mit nur einer Zeile und einem Ganzzahlfeld N 1 und erstellen Sie INSERT TRIGGER, das gerade ausgeführt wird:
Erstellen Sie auch einen DELETE TRIGGER, der Folgendes ausführt:
Ein DBMS, das sein Salz wert ist, garantiert die Atomizität der Operationen über 2 , und N enthält zu jeder Zeit die genaue Anzahl der Zeilen, was dann sehr schnell zu erreichen ist:
Während Trigger DBMS-spezifisch sind, ist die Auswahl von T nicht und Ihr Client-Code muss nicht für jedes unterstützte DBMS geändert werden.
Dies kann jedoch zu Skalierbarkeitsproblemen führen, wenn die Tabelle INSERT- oder DELETE-intensiv ist, insbesondere wenn Sie COMMIT nicht unmittelbar nach INSERT / DELETE ausführen.
1 Diese Namen sind nur Platzhalter - verwenden Sie etwas Bedeutenderes in der Produktion.
2 Dh N kann nicht durch eine gleichzeitige Transaktion zwischen Lesen und Schreiben in N geändert werden, solange sowohl Lesen als auch Schreiben in einer einzigen SQL-Anweisung erfolgen.
quelle
Eine buchstäblich verrückte Antwort, aber wenn Sie eine Art Replikationssystem eingerichtet haben (für ein System mit einer Milliarde Zeilen hoffe ich), können Sie einen groben Schätzer (wie
MAX(pk)
) verwenden und diesen Wert durch die Anzahl der Slaves teilen Sie haben mehrere Abfragen parallel ausgeführt.Zum größten Teil würden Sie die Abfragen auf der Grundlage des besten Schlüssels (oder des Primärschlüssels, denke ich) auf mehrere Slaves verteilen (wir werden 250000000 als unsere Zeilen / Slaves verwenden):
Sie benötigen jedoch nur SQL. Was für eine Büste. Ok, nehmen wir an, Sie sind ein Sadomasochist. Auf dem Master (oder dem nächsten Slave) müssten Sie höchstwahrscheinlich eine Tabelle dafür erstellen:
Anstatt nur die Auswahl in Ihren Slaves auszuführen, müssten Sie eine Einfügung durchführen, ähnlich wie folgt:
Möglicherweise treten Probleme mit Slaves auf, die auf dem Master in eine Tabelle schreiben. Möglicherweise müssen Sie noch mehr Sadis bekommen - ich meine, kreativ:
Sie sollten am Ende einen Slave haben, der zuletzt im Pfad vorhanden ist, der vom Replikationsdiagramm relativ zum ersten Slave durchlaufen wird. Dieser Slave sollte jetzt alle anderen Zählerwerte haben und seine eigenen Werte haben. Aber wenn Sie fertig sind, werden wahrscheinlich Zeilen hinzugefügt, sodass Sie eine weitere einfügen müssen, um das aufgezeichnete maximale pk in Ihrer counter_table und das aktuelle maximale pk zu kompensieren.
Zu diesem Zeitpunkt müssten Sie eine Aggregatfunktion ausführen, um die Gesamtzahl der Zeilen zu ermitteln. Dies ist jedoch einfacher, da Sie sie höchstens auf der Zeile "Anzahl der Slaves, die Sie haben und ändern" ausführen würden.
Wenn Sie in der Situation sind, dass Sie separate Tabellen in den Slaves haben, können
UNION
Sie alle Zeilen abrufen, die Sie benötigen.Oder Sie wissen, seien Sie ein bisschen weniger verrückt und migrieren Sie Ihre Daten auf ein verteiltes Verarbeitungssystem oder verwenden Sie eine Data Warehousing-Lösung (die Ihnen auch in Zukunft eine beeindruckende Datenverarbeitung ermöglicht).
Beachten Sie, dass dies davon abhängt, wie gut Ihre Replikation eingerichtet ist. Da der primäre Engpass höchstwahrscheinlich ein dauerhafter Speicher ist, werden Sie wahrscheinlich langsamer als nur auf einen einzigen warten, wenn Sie über einen groben Speicher oder schlecht getrennte Datenspeicher mit starkem Nachbarrauschen verfügen
SELECT COUNT(*) ...
Wenn Sie jedoch eine gute Replikation haben, sollten Ihre Geschwindigkeitsgewinne in direktem Zusammenhang mit der Anzahl oder den Slaves stehen. Wenn die alleinige Ausführung der Zählabfrage 10 Minuten dauert und Sie 8 Slaves haben, können Sie Ihre Zeit auf weniger als ein paar Minuten verkürzen. Vielleicht eine Stunde, um die Details dieser Lösung auszubügeln.
Natürlich würden Sie nie wirklich eine erstaunlich genaue Antwort erhalten, da diese verteilte Lösung einige Zeit in Anspruch nimmt, in der Zeilen gelöscht und eingefügt werden können, aber Sie können versuchen, eine verteilte Sperre von Zeilen in derselben Instanz zu erhalten und eine genaue Anzahl zu erhalten der Zeilen in der Tabelle für einen bestimmten Zeitpunkt.
Tatsächlich scheint dies unmöglich zu sein, da Sie im Grunde genommen an einer reinen SQL-Lösung festhalten und ich glaube nicht, dass Ihnen ein Mechanismus zur Verfügung gestellt wird, mit dem eine gesplittete und gesperrte Abfrage sofort über mehrere Slaves ausgeführt werden kann. Vielleicht, wenn Sie die Kontrolle über die Replikationsprotokolldatei hätten ... was bedeutet, dass Sie buchstäblich Slaves für diesen Zweck hochfahren würden, was zweifellos langsamer ist, als die Zählabfrage ohnehin nur auf einem einzelnen Computer auszuführen.
Da sind also meine zwei Pennys 2013.
quelle
Wenn die Verwendung des Einfügetriggers zu teuer ist, aber ein Löschtrigger bereitgestellt werden kann und eine automatische Inkrementierung erfolgt
id
, wird die gesamte Tabelle einmal gezählt und die Zählung alslast-count
und gespeichertlast-counted-id
.dann muss jeder Tag nur für
id
> zählenlast-counted-id
, das hinzufügenlast-count
und das neue speichernlast-counted-id
.Der Löschauslöser würde die letzte Zählung verringern, wenn die ID des gelöschten Datensatzes <= die letzte gezählte ID ist.
quelle
Wenn Sie eine typische Tabellenstruktur mit einer automatisch inkrementierenden Primärschlüsselspalte haben, in der Zeilen niemals gelöscht werden, ist das Folgende der schnellste Weg, um die Anzahl der Datensätze zu bestimmen, und sollte in den meisten ANSI-kompatiblen Datenbanken ähnlich funktionieren:
Ich arbeite mit MS SQL-Tabellen, die Milliarden von Zeilen enthalten, die Antwortzeiten von weniger als einer Sekunde für Daten erfordern, einschließlich der Anzahl der Datensätze. Ein ähnlicher SELECT COUNT (*) würde im Vergleich Minuten dauern.
quelle
INSERT
Transaktion zurückgesetzt wird? Dieser Primärschlüsselwert würde fehlen, sodass die tatsächliche Anzahl der Datensätze um eins unter dem Maximalwert liegt.count(*)
wenn ein Datenbankanbieter nicht ausreichend optimiert hatcount(*)
: Verfolgen Sie jeden Tag den letzten automatischen Index und die entsprechende Anzahl und fordern Sie eine Anzahl der darüber hinausgehenden Datensätze an. Kann auch mitdelete
s umgehen, wenn beim Löschen ein Trigger hinzugefügt wird, der die vorherige Summe verringert , wenn die gelöschte Datensatz-ID <= der letzte automatische Index ist.Versuchen Sie dies für SQL Server
quelle
Wählen Sie Zeilen aus sysindexes aus, wobei id = Object_ID ('TableName') und indid <2
quelle
Setzen Sie einen Index auf eine Spalte. Dies sollte es dem Optimierer ermöglichen, einen vollständigen Scan der Indexblöcke anstelle eines vollständigen Scans der Tabelle durchzuführen. Dadurch werden Ihre E / A-Kosten erheblich gesenkt. Schauen Sie sich vorher und nachher den Ausführungsplan an. Messen Sie dann die Wanduhrzeit in beide Richtungen.
quelle
Wenn Sie Oracle verwenden, wie wäre es damit (vorausgesetzt, die Tabellenstatistiken werden aktualisiert):
last_analyzed zeigt die Zeit an, zu der die Statistiken zuletzt gesammelt wurden.
quelle
Mit PostgreSQL:
quelle
In SQL Server 2016 kann ich einfach die Tabelleneigenschaften überprüfen und dann die Registerkarte "Speicher" auswählen. Dies gibt mir die Zeilenanzahl, den von der Tabelle verwendeten Speicherplatz, den verwendeten Indexbereich usw. an.
quelle
database vendor independent solution
. Auch dies erfordert eine GUI und kann nicht automatisiert werden. Auch ist es nicht schneller als COUNT (*)Vielleicht etwas spät, aber dies könnte anderen für MSSQL helfen
quelle