La meilleure façon de tester si une ligne existe dans une table MySQL
J'essaie de savoir si une ligne existe dans une table. L'utilisation de MySQL, est-il préférable de faire une requête comme ceci:
SELECT COUNT(*) AS total FROM table1 WHERE ...
et vérifier pour voir si le total est non-nul, ou est-il préférable de faire une requête comme ceci:
SELECT * FROM table1 WHERE ... LIMIT 1
et vérifier pour voir si toutes les lignes ont été retournés?
Dans les deux requêtes, la clause where utilise un index.
Vous devez vous connecter pour publier un commentaire.
Vous pouvez également essayer d'utiliser
par la documentation
Par un commentaire ci-dessous:
...EXISTS( SELECT 1/0 FROM someothertable)
. Pour SQL Server & Oracle - il ne fait aucune différence à utiliser *, 1 ou NULLE, car il EXISTE seulement des tests pour un booléen basé sur 1+ d'OÙ les critères d'appariement.SELECT 1 FROM table1 WHERE col = $var LIMIT 1
est plus rapide que votre requête. Alors, quel est l'avantage de votre requête?SELECT 1 FROM test WHERE ... LIMIT 1
, sansSELECT EXISTS
autour d'elle. Peut-être un poil plus rapide de cette façon.J'ai fait quelques recherches à ce sujet récemment. La façon de mettre en œuvre elle doit être différente si le champ est un champ de TEXTE, un champ unique.
J'ai fait quelques tests avec un champ de TEXTE. Compte tenu du fait que nous avons une table avec 1M d'entrées. 37 entrées sont égales à "quelque chose":
SELECT * FROM test WHERE texte LIKE '%something%' LIMIT 1
avecmysql_num_rows()
: 0.039061069488525 s. (Plus RAPIDE)SELECT count(*) as count FROM test WHERE text LIKE '%something%
:16.028197050095 s.
SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%')
:0.87045907974243 s.
SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%'
: 0.044898986816406 s.LIMIT 1)
Mais maintenant, avec un BIGINT PK champ, une seule entrée est égal à '321321' :
SELECT * FROM test2 WHERE id ='321321' LIMIT 1
avecmysql_num_rows()
: 0.0089840888977051 s.SELECT count(*) as count FROM test2 WHERE id ='321321'
: 0.00033879280090332 s.SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321')
: 0.00023889541625977 s.SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321' LIMIT 1)
: 0.00020313262939453 s. (Plus RAPIDE)SELECT 1 FROM test WHERE texte LIKE '%something%' LIMIT 1
select 1 ... limit 1
, il est inutile de les entourer avec sélectionnez existeSELECT 1 FROM test WHERE ...
, sansSELECT EXISTS
autour d'elle. Sans doute un poil plus rapide de cette façon.id
...SELECT 1 FROM ... WHERE ... LIMIT 1
vous donnera le meilleur des deux mondes.. ajouter le EXISTE d'emballage si vous avez besoin d'un retour boolean pour pas de lignes correspondantes.Un court exemple de @ChrisThompson la réponse de
Exemple:
À l'aide d'un alias:
Dans mes recherches, je trouve le résultat à obtenir sur la suite de vitesse.
Je pense qu'il est intéressant de souligner, bien qu'il ait été abordé dans les commentaires, que dans cette situation:
Est supérieur à:
C'est parce que la première requête peut être satisfaite par l'indice, alors que la seconde nécessite une ligne rechercher (sauf peut-être toutes les colonnes de la table sont dans l'index utilisé).
L'ajout de la
LIMIT
clause permet au moteur de s'arrêter après de trouver n'importe quelle ligne.La première requête doit être comparable:
Qui envoie les signaux vers le moteur (1/* ne fait pas de différence ici), mais je serais encore écrire l'1 à renforcer l'habitude lors de l'utilisation de
EXISTS
:Il peut être judicieux d'ajouter le
EXISTS
d'emballage si vous avez besoin d'un retour explicite lorsqu'aucune correspondance de lignes.Vous suggérons de ne pas utiliser
Count
parce que le comte a toujours fait des charges supplémentaires pour la db utiliserSELECT 1
et il retourne 1 si votre dossier là sinon elle renvoie null et que vous pouvez le manipuler.Parfois il est assez pratique pour obtenir l'incrément automatique de la clé primaire (
id
) de la ligne si elle existe et0
si elle ne le fait pas.Voici comment cela peut être fait en une seule requête:
IFNULL(id, 0)
ici au lieu de laCOUNT(*)
?J'irais avec
COUNT(1)
. Il est plus rapide queCOUNT(*)
parce queCOUNT(*)
des tests pour voir si au moins une colonne de la rangée est != La valeur NULL. Vous n'avez pas besoin de cela, surtout parce que vous disposez déjà d'une condition en place (leWHERE
clause).COUNT(1)
au lieu teste la validité de1
, qui est toujours valable et prend beaucoup moins de temps pour tester.Un Le COMTE requête est plus rapide, bien que peut-être pas sensiblement, mais jusqu'à obtenir le résultat souhaité, à la fois devrait suffire.
Pour les non-tables InnoDB vous pouvez également utiliser les informations de schéma de tables:
http://dev.mysql.com/doc/refman/5.1/en/tables-table.html
Ou vous pouvez insérer raw sql partie à des conditions
j'ai donc
'conditions'=>array('Membre.id not IN (SELECT Membres.member_id D'abonnements QUE l'Adhésion)')
COUNT(*)
sont optimisés en MySQL, de sorte que l'ancienne requête est susceptible d'être plus rapide, d'une manière générale.