Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Ist es besser, eine Ergebnismenge mit einer WHERE-Klausel oder mit Anwendungscode zu filtern?

Die Faustregel für jede Anwendung lautet, die Datenbank die Dinge tun zu lassen, die sie gut kann:Filtern, Sortieren und Verbinden.

Trennen Sie die Abfragen in ihre eigenen Funktionen oder Klassenmethoden:

$men = $foo->fetchMaleUsers();
$women = $foo->fetchFemaleUsers();

Aktualisieren

Ich habe Stevens PostgreSQL-Demonstration einer Abfrage mit vollständigem Tabellenscan verwendet, die doppelt so gut ist wie zwei separate indizierte Abfragen, und sie mit MySQL nachgeahmt (das in der eigentlichen Frage verwendet wird):

Schema

CREATE TABLE `gender_test` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `gender` enum('male','female') NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26017396 DEFAULT CHARSET=utf8

Ich habe den Geschlechtstyp so geändert, dass er kein VARCHAR(20) ist, da dies für den Zweck dieser Spalte realistischer ist. Außerdem stelle ich einen Primärschlüssel bereit, wie Sie es in einer Tabelle erwarten würden, anstelle eines beliebigen DOUBLE-Werts.

Nicht indizierte Ergebnisse

mysql> select sql_no_cache * from gender_test WHERE gender = 'male';

12995993 rows in set (31.72 sec)

mysql> select sql_no_cache * from gender_test WHERE gender = 'female';

13004007 rows in set (31.52 sec)

mysql> select sql_no_cache * from gender_test;

26000000 rows in set (32.95 sec)

Ich vertraue darauf, dass dies keiner Erklärung bedarf.

Indizierte Ergebnisse

ALTER TABLE gender_test ADD INDEX (gender);

...

mysql> select sql_no_cache * from gender_test WHERE gender = 'male';

12995993 rows in set (15.97 sec)

mysql> select sql_no_cache * from gender_test WHERE gender = 'female';

13004007 rows in set (15.65 sec)

mysql> select sql_no_cache * from gender_test;

26000000 rows in set (27.80 sec)

Die hier gezeigten Ergebnisse sind radikal anders als Stevens Daten. Die indizierten Abfragen führen fast aus doppelt so schnell wie der Full-Table-Scan. Dies stammt aus einer ordnungsgemäß indizierten Tabelle, die vernünftige Spaltendefinitionen verwendet. Ich kenne PostgreSQL überhaupt nicht, aber in Stevens Beispiel muss eine erhebliche Fehlkonfiguration vorliegen, damit keine ähnlichen Ergebnisse angezeigt werden.

Angesichts des Rufs von PostgreSQL, Dinge besser zu machen als MySQL, oder zumindest so gut wie, wage ich zu behaupten, dass PostgreSQL bei richtiger Verwendung eine ähnliche Leistung zeigen würde.

Beachten Sie auch, dass auf derselben Maschine eine zu stark vereinfachte for-Schleife, die 52 Millionen Vergleiche durchführt, zusätzliche 7,3 Sekunden benötigt auszuführen.

<?php
$N = 52000000;
for($i = 0; $i < $N; $i++) {
    if (true == true) {
    }
}

Ich denke, es ist ziemlich offensichtlich, was angesichts dieser Daten der bessere Ansatz ist.