Mysql
 sql >> Base de données >  >> RDS >> Mysql

Est-il préférable de filtrer un jeu de résultats à l'aide d'une clause WHERE ou à l'aide d'un code d'application ?

La règle d'or pour toute application est de laisser la base de données faire ce qu'elle fait bien :filtrer, trier et joindre.

Séparez les requêtes en leurs propres fonctions ou méthodes de classe :

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

Mettre à jour

J'ai pris la démonstration PostgreSQL de Steven d'une requête d'analyse de table complète deux fois plus performante que deux requêtes indexées distinctes et je l'ai imitée à l'aide de MySQL (qui est utilisé dans la question réelle) :

Schéma

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

J'ai changé le type de genre pour ne pas être un VARCHAR(20) car il est plus réaliste pour les besoins de cette colonne, je fournis également une clé primaire comme on peut s'y attendre sur une table au lieu d'une valeur DOUBLE arbitraire.

Résultats non indexés

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)

J'espère que cela n'a pas besoin d'explication.

Résultats indexés

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)

Les résultats présentés ici sont radicalement différent des données de Steven. Les requêtes indexées fonctionnent presque deux fois plus rapide que le balayage complet de la table. Cela provient d'une table correctement indexée utilisant des définitions de colonne de bon sens. Je ne connais pas du tout PostgreSQL, mais il doit y avoir une erreur de configuration importante dans l'exemple de Steven pour ne pas afficher des résultats similaires.

Étant donné la réputation de PostgreSQL de faire les choses mieux que MySQL, ou du moins aussi bien, j'ose dire que PostgreSQL démontrerait des performances similaires s'il était correctement utilisé.

Notez également que sur cette même machine, une boucle for trop simplifiée faisant 52 millions de comparaisons prend 7,3 secondes supplémentaires à exécuter.

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

Je pense qu'il est assez évident quelle est la meilleure approche compte tenu de ces données.