J'essaie de savoir si une ligne existe dans une table. En utilisant MySQL, est-il préférable de faire une requête comme celle-ci:
SELECT COUNT(*) AS total FROM table1 WHERE ...
et vérifiez si le total est différent de zéro ou est-il préférable de faire une requête comme celle-ci:
SELECT * FROM table1 WHERE ... LIMIT 1
et vérifier si des lignes ont été retournées?
Dans les deux requêtes, la clause WHERE utilise un index.
sql
mysql
performance
exists
Bernard Chen
la source
la source
...EXISTS( SELECT 1/0 FROM someothertable)
. Pour SQL Server et Oracle - cela ne fait aucune différence d'utiliser *, 1 ou NULL car EXISTS ne teste qu'un booléen basé sur 1+ des critères WHERE correspondant.SELECT 1 FROM table1 WHERE col = $var LIMIT 1
est plus rapide que votre requête. Quel est donc l'avantage de votre requête?J'ai fait quelques recherches sur ce sujet récemment. La façon de l'implémenter doit être différente si le champ est un champ TEXTE, un champ non unique.
J'ai fait quelques tests avec un champ TEXT. 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,039061069488525s. (PLUS RAPIDE)SELECT count(*) as count FROM test WHERE text LIKE '%something%
: 16.028197050095s.SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%')
: 0.87045907974243s.SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%' LIMIT 1)
: 0,044898986816406s.Mais maintenant, avec un champ BIGINT PK, une seule entrée est égale à '321321':
SELECT * FROM test2 WHERE id ='321321' LIMIT 1
avecmysql_num_rows()
: 0,0089840888977051s.SELECT count(*) as count FROM test2 WHERE id ='321321'
: 0.00033879280090332s.SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321')
: 0,00023889541625977s.SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321' LIMIT 1)
: 0.00020313262939453s. (PLUS RAPIDE)la source
SELECT 1 FROM test WHERE texte LIKE '%something%' LIMIT 1
select 1 ... limit 1
, il est inutile de s'entourer de select existeSELECT 1 FROM test WHERE ...
, c'est sansSELECT EXISTS
autour. Vraisemblablement, les cheveux sont plus rapides de cette façon.Un bref exemple de la réponse de @ ChrisThompson
Exemple:
Utilisation d'un alias:
la source
Dans mes recherches, je peux trouver le résultat à la vitesse suivante.
la source
Je pense qu'il convient de souligner, bien que cela ait été évoqué dans les commentaires, que dans cette situation:
Est supérieur à:
En effet, la première requête peut être satisfaite par l'index, tandis que la seconde nécessite une recherche de ligne (sauf si toutes les colonnes de la table se trouvent dans l'index utilisé).
L'ajout de la
LIMIT
clause permet au moteur de s'arrêter après avoir trouvé une ligne.La première requête doit être comparable à:
Ce qui envoie les mêmes signaux au moteur (1 / * ne fait aucune différence ici), mais j'écrirais toujours le 1 pour renforcer l'habitude lors de l'utilisation
EXISTS
:Il peut être judicieux d'ajouter l'
EXISTS
habillage si vous avez besoin d'un retour explicite lorsqu'aucune ligne ne correspond.la source
Nous vous suggérons de ne pas l'utiliser,
Count
car le nombre crée toujours des charges supplémentaires pour l'utilisation de la base de donnéesSELECT 1
et renvoie 1 si votre enregistrement est là, sinon, il renvoie null et vous pouvez le gérer.la source
Une requête COUNT est plus rapide, bien que peut-être pas sensiblement, mais en ce qui concerne l'obtention du résultat souhaité, les deux devraient être suffisants.
la source
Parfois, il est très pratique d'obtenir la clé primaire d'incrémentation automatique (
id
) de la ligne si elle existe et0
si elle n'existe pas.Voici comment cela peut être fait en une seule requête:
la source
IFNULL(id, 0)
ici au lieu deCOUNT(*)
?Pour les tables non InnoDB, vous pouvez également utiliser les tables de schéma d'information:
http://dev.mysql.com/doc/refman/5.1/en/tables-table.html
la source
J'irais avec
COUNT(1)
. C'est plus rapide queCOUNT(*)
parce que desCOUNT(*)
tests pour voir si au moins une colonne de cette ligne est! = NULL. Vous n'en avez pas besoin, surtout parce que vous avez déjà une condition en place (laWHERE
clause).COUNT(1)
teste plutôt la validité de1
, qui est toujours valide et prend beaucoup moins de temps à tester.la source
Ou vous pouvez insérer une partie SQL brute dans les conditions pour que j'aie 'conditions' => tableau ('Member.id NOT IN (SELECT Membership.member_id FROM memberships AS Membership)'))
la source
COUNT(*)
sont optimisés dans MySQL, donc l'ancienne requête est susceptible d'être plus rapide, d'une manière générale.la source