web-dev-qa-db-fra.com

Meilleure façon de vérifier si une ligne existe dans une table MySQL

J'essaie de savoir si une ligne existe dans une table. Avec MySQL, vaut-il mieux 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 s'il est 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.

305
Bernard Chen

Vous pouvez également essayer d'utiliser

SELECT EXISTS(SELECT * FROM table1 WHERE ...)

par la documentation

Par un commentaire ci-dessous:

SELECT EXISTS(SELECT 1 FROM table1 WHERE ...)
432
Chris Thompson

J'ai fait des recherches sur ce sujet récemment. La manière de l'implémenter doit être différente si le champ est un champ TEXT, un champ non unique.

J'ai fait des tests avec un champ TEXT. Considérant le fait que nous avons une table avec 1M entrées. 37 entrées sont égales à 'quelque chose':

  • SELECT * FROM test WHERE texte LIKE '%something%' LIMIT 1 avec mysql_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 avec mysql_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)
169
Laurent W.

Un petit exemple de la réponse de @ ChrisThompson

Exemple:

mysql> SELECT * FROM table_1;
+----+--------+
| id | col1   |
+----+--------+
|  1 | foo    |
|  2 | bar    |
|  3 | foobar |
+----+--------+
3 rows in set (0.00 sec)

mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 1);
+--------------------------------------------+
| EXISTS(SELECT 1 FROM table_1 WHERE id = 1) |
+--------------------------------------------+
|                                          1 |
+--------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 9);
+--------------------------------------------+
| EXISTS(SELECT 1 FROM table_1 WHERE id = 9) |
+--------------------------------------------+
|                                          0 |
+--------------------------------------------+
1 row in set (0.00 sec)

Utiliser un alias:

mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 1) AS mycheck;
+---------+
| mycheck |
+---------+
|       1 |
+---------+
1 row in set (0.00 sec)
23
jaltek

Dans mes recherches, je peux trouver le résultat qui suit la vitesse suivante.

select * from table where condition=value
(1 total, Query took 0.0052 sec)

select exists(select * from table where condition=value)
(1 total, Query took 0.0008 sec)

select count(*) from table where condition=value limit 1) 
(1 total, Query took 0.0007 sec)

select exists(select * from table where condition=value limit 1)
(1 total, Query took 0.0006 sec) 
10
shihab mm

Je pense qu'il convient de souligner, bien que cela ait été mentionné dans les commentaires, que dans cette situation:

SELECT 1 FROM my_table WHERE *indexed_condition* LIMIT 1

Est supérieur à:

SELECT * FROM my_table WHERE *indexed_condition* LIMIT 1

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 sont dans l'index utilisé).

L'ajout de la clause LIMIT permet au moteur de s'arrêter après avoir trouvé une ligne.

La première requête doit être comparable à:

SELECT EXISTS(SELECT * FROM my_table WHERE *indexed_condition*)

Ce qui envoie les mêmes signaux au moteur (1/* ne fait aucune différence ici), mais j'écrirais quand même le 1 pour renforcer l'habitude d'utiliser EXISTS:

SELECT EXISTS(SELECT 1 FROM my_table WHERE *indexed_condition*)

Il peut être judicieux d'ajouter le retour à la ligne EXISTS si vous avez besoin d'un retour explicite lorsqu'aucune ligne ne correspond.

7
Arth

Nous vous suggérons de ne pas utiliser Count car count compte toujours des charges supplémentaires pour la base de données. Utilisez SELECT 1 et renvoie 1 si votre enregistrement se trouve là, sinon il renvoie null et vous pouvez le gérer.

4
Fatih Karatana

Parfois, il est assez pratique d’obtenir la clé primaire d’incrémentation automatique (id) de la ligne si elle existe et 0 si elle n’existe pas.

Voici comment cela peut être fait en une seule requête:

SELECT IFNULL(`id`, COUNT(*)) FROM WHERE ...
2
Zaxter

Une requête COUNT est plus rapide, mais peut-être pas sensiblement, mais pour obtenir le résultat souhaité, les deux doivent être suffisant.

0
jaywon

J'irais avec COUNT(1). Il est plus rapide que COUNT(*) parce que COUNT(*) teste 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 (la clause WHERE). COUNT(1) teste à la place la validité de 1, qui est toujours valide et prend beaucoup moins de temps à tester.

0
Felix