Frage

Ich weiß, es ist generell eine schlechte Idee Abfragen wie dies zu tun:

SELECT * FROM `group_relations`

Aber wenn ich will nur die Anzahl, soll ich für diese Abfrage gehen, da, dass die Tabelle erlaubt aber immer noch zu ändern, ergibt die gleichen Ergebnisse.

SELECT COUNT(*) FROM `group_relations`

oder die mehr specfic

SELECT COUNT(`group_id`) FROM `group_relations`

Ich habe das Gefühl, diese potenziell schneller sein könnten, aber gibt es andere Dinge zu beachten?

Aktualisieren . Ich bin mit InnoDB in diesem Fall leider für nicht spezifischere sein

War es hilfreich?

Lösung

Wenn die betreffende Spalte NOT NULL ist, sind beide Ihre Abfragen gleichwertig. Wenn group_id Nullwerte enthält,

select count(*)

werden alle Zeilen zählen, während

select count(group_id)

wird nur die Zeilen zählen, wo group_id nicht null ist.

Auch einige Datenbanksysteme wie MySQL eine Optimierung verwenden, wenn Sie für Zählung fragen (*), die solche Abfragen ein bisschen schneller als die spezifischen macht.

Persönlich, wenn nur das Zählen, ich tue count (*) mit den Nullen auf der sicheren Seite zu sein.

Andere Tipps

Wenn ich es mir recht erinnere, in MYSQL COUNT (*) zählt alle Reihen, während COUNT (column_name) zählt nur die Zeilen, die einen Nicht-NULL-Wert in der angegebenen Spalte haben.

COUNT (*) zählen alle Zeilen während COUNT (Spaltenname) nur die Zeilen ohne NULL-Werte in der angegebenen Spalte zählen wird.

Wichtig in MySQL zu beachten:

COUNT () ist sehr schnell auf MyISAM-Tabellen für * oder nicht-null-Spalten, da die Zeilenanzahl zwischengespeichert wird. InnoDB hat keine Zeilenanzahl Caching, so gibt es keinen Unterschied in der Leistung für COUNT (*) oder COUNT (Spalten_Name), unabhängig davon, ob die Spalte null sein kann oder nicht. Sie können mehr über die Unterschiede auf diesen Beitrag bei der Lese MySQL Performance Blog.

Wenn Sie SELECT COUNT(1) FROMgroup_relations versuchen wird es ein bisschen schneller sein, weil es nicht Informationen aus Spalten abrufen werden versuchen.

Edit: Ich habe gerade einige der Forschung und fand heraus, dass dies nur in einigen db passiert. In Sqlserver ist es die gleiche 1 oder * zu verwenden, aber auf Oracle ist es schneller 1 zu verwenden.

http: //social.msdn.microsoft.com/forums/en-US/transactsql/thread/9367c580-087a-4fc1-bf88-91a51a4ee018/

Anscheinend gibt es keinen Unterschied zwischen ihnen in mysql, wie Sqlserver erscheint der Parser die Abfrage ändern auswählen (1). Sorry, wenn ich die Irre führen Sie in irgendeiner Weise.

Ich war neugierig auf diese selbst. Es ist alles in Ordnung Dokumentation und theoretische Antworten zu lesen, aber Ich mag die mit empirischen Daten balancieren.

Ich habe eine MySQL-Tabelle (InnoDB), die 5.607.997 Datensätze in ihm hat. Der Tisch ist in meinem eigenen Sandbox, so dass ich weiß, dass die Inhalte sind statisch und niemand sonst wird mit dem Server. Ich denke, das effektiv alle außen wirkt sich auf die Leistung entfernt. Ich habe eine Tabelle mit einem auto_increment Primärschlüsselfeld (Id), die ich kenne wird nie Null sein, dass ich für meinen where-Klausel Test verwenden (WHERE Id IS NOT NULL).

Die einzige andere mögliche Panne ich in laufenden Tests sehen, ist der Cache. Das erste Mal, wenn eine Abfrage ausgeführt wird, wird immer langsamer als nachfolgende Abfragen, die die gleichen Indizes verwenden. Ich werde im Folgenden als Cache-Seeding Aufruf, dass verweisen. Nur um es zu mischen, um ein wenig bis ich lief es mit einer where-Klausel ich weiß, wird immer als wahr ausgewertet, unabhängig von irgendwelchen Daten (TRUE = TRUE).

Wie gesagt hier sind meine Ergebnisse:

querytype

      |  w/o WHERE          | where id is not null |  where true=true

COUNT ()

      |  9 min 30.13 sec ++ | 6 min 16.68 sec ++   | 2 min 21.80 sec ++
      |  6 min 13.34 sec    | 1 min 36.02 sec      | 2 min 0.11 sec 
      |  6 min 10.06 se     | 1 min 33.47 sec      | 1 min 50.54 sec

COUNT (Id)

      |  5 min 59.87 sec    | 1 min 34.47 sec      | 2 min 3.96 sec 
      |  5 min 44.95 sec    | 1 min 13.09 sec      | 2 min 6.48 sec

COUNT (1)

      | 6 min 49.64 sec    | 2 min 0.80 sec       | 2 min 11.64 sec
      | 6 min 31.64 sec    | 1 min 41.19 sec      | 1 min 43.51 sec

++ Dies ist der Cache Seeding Anruf betrachtet. Es wird erwartet, langsamer zu sein als der Rest.

Ich würde sagen, die Ergebnisse sprechen für sich. COUNT (Id) Kanten in der Regel der andere aus. Hinzufügen eines Where-Klausel dramatisch die Zugriffszeit verringert mich, auch wenn es eine Klausel, Sie wissen, wird auf true bewerten. Der Sweet Spot erscheint COUNT (Id) zu sein ... WHERE Id IS NOT NULL.

Ich würde lieben, andere Völker zu sehen, Ergebnisse, vielleicht mit kleineren Tabellen oder mit denen Klauseln gegen andere Felder als das Feld Sie zählen. Ich bin sicher, es gibt auch andere Variationen mich nicht berücksichtigt haben.

Sucht Alternativen

Wie Sie gesehen haben, wenn Tabellen groß werden, erhalten COUNT Abfragen langsam. Ich denke, das Wichtigste ist, die Art des Problems zu betrachten Sie versuchen zu lösen. Zum Beispiel verwenden viele Entwickler COUNT Abfragen, wenn die Paginierung für große Gruppen von Datensätzen, um die Gesamtzahl der Seiten in der Ergebnismenge zu erzeugen, um zu bestimmen.

Das Wissen, dass COUNT Abfragen langsam wachsen wird, könnten Sie eine alternative Art und Weise betrachten Paginierung Steuerelemente anzuzeigen, die einfach können Sie die langsame Abfrage Seite-Schritt. Googles Paginierung ist ein ausgezeichnetes Beispiel.

denormalize

Wenn Sie unbedingt die Anzahl der Datensätze wissen muss eine bestimmte Zählung übereinstimmt, die klassische Technik der Datennormalisierungs betrachten. Statt die Anzahl der Zeilen bei Lookup Zeit zu zählen, sollten Sie einen Zähler auf Rekord Einfügung Erhöhen und Erniedrigen, daß der Zähler auf Löschen von Datensätzen.

Wenn Sie sich entscheiden, dies zu tun, sollten Sie mit idempotent, transaktionale Operationen jene denormalized Werte synchron zu halten.

BEGIN TRANSACTION;
INSERT INTO  `group_relations` (`group_id`) VALUES (1);
UPDATE `group_relations_count` SET `count` = `count` + 1;
COMMIT;

Alternativ können Sie verwenden Datenbank-Trigger, wenn Ihr RDBMS unterstützt werden.

Je nach Architektur, könnte es sinnvoll, eine Caching-Schicht wie Memcached zu verwenden, zu speichern, zu erhöhen bzw. verringern die normalisierte Wert, und fallen einfach durch die langsame COUNT Abfrage, wenn der Cache-Schlüssel fehlt. Dies kann die Gesamtschreib Konflikte reduzieren, wenn Sie sehr volatile Daten haben, wenn auch in Fällen wie diesen, sollten Sie Lösungen für den Hundehaufen Effekt .

MySQL ISAM Tabellen sollten Optimierung für COUNT (*) haben, das Überspringen Full Table Scan.

Ein Sternchen in COUNT hat kein Lager mit Sternchen für alle Felder der Tabelle. Es ist reiner Unsinn, dass COUNT zu sagen (*) ist langsamer als COUNT (Feld)

ich spüren, dass SELECT COUNT (*) ist schneller als SELECT COUNT (Feld). Wenn das RDBMS festgestellt, dass Sie „*“ auf COUNT statt Feld angeben, braucht es nicht, etwas zu bewerten Anzahl zu erhöhen. Während, wenn Sie Feld auf COUNT angeben, wird das RDBMS immer beurteilen, wenn Ihr Feld null ist oder nicht, es zu zählen.

Aber wenn Ihr Feld NULL-Werte zulässt, geben Sie das Feld in COUNT.

COUNT (*) Fakten und Mythen:

MYTHOS : "InnoDB nicht verarbeitet count (*) Abfragen gut":

Die meisten count (*) Abfragen gleiche Art und Weise durch alle Speicher-Engines ausgeführt werden, wenn Sie eine WHERE-Klausel haben, sonst werden Sie InnoDB haben einen vollständigen Tabellenscan durchzuführen.

FACT : InnoDB optimiert nicht count (*) Abfragen ohne die where-Klausel

Es ist am besten durch eine indexierte Spalte zu zählen, wie beispielsweise einen Primärschlüssel.

SELECT COUNT(`group_id`) FROM `group_relations`

Es sollte davon abhängen, was Sie versuchen, tatsächlich zu erreichen, wie Sebastian schon gesagt hat, das heißt, Ihre Absichten klar machen! Wenn Sie ist nur die Zeilen zu zählen dann für die COUNT gehen (*) oder eine einzelne Spalte für die COUNT geht Zählung (Spalte).

Es könnte sich lohnen, Ihre DB-Anbieter auch heraus überprüfen. Damals, als ich verwenden Informix verwenden, um es hatte eine Optimierung für COUNT (*), die im Vergleich zum Zählen einzelner oder mehrfachiger Spalten einen Abfrageplan Ausführungskosten von 1 hatte, die in einem höheren Ergebnis führen würden

  

Wenn Sie SELECT COUNT versuchen (1) FROM group_relations wird es ein bisschen schneller sein, weil es nicht Informationen aus Spalten abrufen werden versuchen.

COUNT (1) verwendet als COUNT schneller zu sein (*), aber das ist nicht mehr wahr, da moderne DBMS klug genug zu wissen, dass Sie nicht wollen, über Spalten weiß es

Der Rat, den ich von MySQL habe über Dinge wie diese ist, dass in der Regel versuchen, eine Abfrage auf Tricks wie diese Basis zu optimieren, kann ein Fluch auf lange Sicht sein. Es gibt Beispiele, über die MySQL-Geschichte, wo jemand High-Performance-Technik, die auf beruht, wie der Optimierer arbeitet der Engpass in der nächsten Version endet als.

Schreiben Sie die Abfrage, die die Frage beantwortet Sie fragen - wenn Sie eine Zählung aller Zeilen möchten, verwenden Sie COUNT (*). Wenn Sie eine Anzahl von Nicht-Null-Spalten möchten, verwenden Sie COUNT (col) WHERE col IS NOT NULL. Index entsprechend, und die Optimierung für das Optimierungsprogramm verlassen. Der Versuch, Ihre eigenen Abfrage-Level-Optimierungen machen kann manchmal macht das eingebaute in Optimierer weniger wirksam.

Das heißt, es gibt Dinge, die Sie in einer Abfrage tun können, um es einfacher für das Optimierungsprogramm um ihn zu beschleunigen, aber ich glaube nicht, COUNT einer von ihnen ist.

Edit: Die Statistiken in der Antwort oben interessant sind, though. Ich bin nicht sicher, ob es tatsächlich etwas bei der Arbeit in den Optimierer in diesem Fall ist. Ich spreche nur über Abfrage-Level-Optimierungen im Allgemeinen.

  

Ich weiß, es ist generell eine schlechte Idee zu tun   Abfragen wie folgt:

SELECT * FROM `group_relations`
     

Aber wenn ich die Zählung nur wollen, sollten   Ich gehe für diese Abfrage, da dies erlaubt   die Tabelle zu ändern, aber nach wie vor ergibt   die gleichen Ergebnisse.

SELECT COUNT(*) FROM `group_relations`

Wie Sie Ihre Frage impliziert, ist der Grund, SELECT * schlecht beraten ist, dass Änderungen an der Tabelle Änderungen in Ihrem Code erforderlich machen könnten. Das gilt nicht für COUNT(*). Es ist ziemlich selten, die spezialisierte Verhalten zu wollen, dass SELECT COUNT('group_id') Sie gibt - in der Regel die Anzahl der Datensätze wissen wollen. Das ist, was COUNT(*) ist, so dass es verwendet werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top