web-dev-qa-db-fra.com

Différences de performances entre égal (=) et IN avec une valeur

En quoi les moteurs SQL diffèrent-ils lorsque nous utilisons un signe égal et que l'opérateur IN a la même valeur? Le temps d'exécution change-t-il?

1er utilisant l'opérateur de vérification d'égalité

WHERE column_value = 'All'

2ème en utilisant OR opérateur et valeur unique

WHERE column_value IN ('All')

Le moteur SQL change-t-il IN en = s'il n'y a qu'une seule valeur?

Y a-t-il une différence pour MySQL et PostgreSQL?

54
Somnath Muluk

Il n'y a aucune différence entre ces deux instructions, et l'optimiseur transformera le IN en = Lorsque IN n'aura qu'un seul élément dedans.

Bien que lorsque vous avez une question comme celle-ci, exécutez simplement les deux instructions, exécutez leur plan d'exécution et voyez les différences. Ici - vous n'en trouverez pas.

Après une grande recherche en ligne, j'ai trouvé un document sur SQL pour supporter cela (je suppose qu'il s'applique à tous les SGBD):

S'il n'y a qu'une seule valeur entre parenthèses, cette recommandation équivaut à

OERE "nom_colonne" = 'valeur1

Voici le lien vers le document .

Voici le plan d'exécution des deux requêtes dans Oracle (la plupart des SGBD traiteront la même chose):

EXPLAIN PLAN FOR
select * from dim_employees t
where t.identity_number = '123456789'

Plan hash value: 2312174735
-----------------------------------------------------
| Id  | Operation                   | Name          |
-----------------------------------------------------
|   0 | SELECT STATEMENT            |               |
|   1 |  TABLE ACCESS BY INDEX ROWID| DIM_EMPLOYEES |
|   2 |   INDEX UNIQUE SCAN         | SYS_C0029838  |
-----------------------------------------------------

Et pour IN():

EXPLAIN PLAN FOR
select * from dim_employees t
where t.identity_number in('123456789');

Plan hash value: 2312174735
-----------------------------------------------------
| Id  | Operation                   | Name          |
-----------------------------------------------------
|   0 | SELECT STATEMENT            |               |
|   1 |  TABLE ACCESS BY INDEX ROWID| DIM_EMPLOYEES |
|   2 |   INDEX UNIQUE SCAN         | SYS_C0029838  |
-----------------------------------------------------

Comme vous pouvez le voir, les deux sont identiques. C'est sur une colonne indexée. Il en va de même pour une colonne non indexée (juste une analyse complète de la table).

56
sagi

Il n'y a aucune différence lorsque vous l'utilisez avec une seule valeur. Si vous vérifiez l'analyse de table, l'analyse d'index ou la recherche d'index pour les deux requêtes ci-dessus, vous constaterez qu'il n'y a pas de différence entre les deux requêtes.

Y a-t-il une différence pour Mysql et PostgresSQL?

Non, cela n'aurait aucune différence sur les deux moteurs (En fait, ce serait la même chose pour la plupart des bases de données, y compris SQL Server, Oracle, etc.). Les deux moteurs convertiront IN en =

8
Rahul Tripathi

Il n'y a pas vraiment de grandes différences, mais si votre column_value est indexé, l'opérateur IN peut ne pas le lire comme un index.

Vous avez rencontré ce problème une fois, alors soyez prudent.

6
John

Apprenez à un homme à pêcher, etc. Voici comment voir par vous-même les variations de vos requêtes:

mysql> EXPLAIN SELECT * FROM sentence WHERE sentence_lang_id = "AMH"\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: sentence
         type: ref
possible_keys: sentence_lang_id
          key: sentence_lang_id
      key_len: 153
          ref: const
         rows: 442
        Extra: Using where

Et essayons dans l'autre sens:

mysql> EXPLAIN SELECT * FROM sentence WHERE sentence_lang_id in ("AMH")\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: sentence
         type: ref
possible_keys: sentence_lang_id
          key: sentence_lang_id
      key_len: 153
          ref: const
         rows: 442
        Extra: Using where

Vous pouvez lire ici sur la façon d'interpréter les résultats d'une requête mysql EXPLAIN. Pour l'instant, notez que nous avons obtenu une sortie identique pour les deux requêtes: exactement le même "plan d'exécution" est généré. La ligne type nous indique que la requête utilise un index non unique (une clé étrangère, dans ce cas), et la ligne ref nous indique que la requête est exécutée en comparant une valeur constante contre cet indice.

5
alexis

Pour une clause IN unique, il n'y a pas de différence ... ci-dessous est une démonstration utilisant une table EMPS que j'ai ..

select * from emps where empid in (1)
select * from emps where empid=1

Prédicat pour la première requête dans le plan d'exécution:

[PerformanceV3].[dbo].[Emps].[empID]=CONVERT_IMPLICIT(int,[@1],0)

Prédicat pour la deuxième requête dans le plan d'exécution:

[PerformanceV3].[dbo].[Emps].[empID]=CONVERT_IMPLICIT(int,[@1],0)

Si vous avez plusieurs valeurs dans la clause IN, il est préférable de les convertir en jointures

4
TheGameiswar

Juste pour ajouter une perspective différente, l'un des principaux points des systèmes rdbms est qu'ils réécriront votre requête pour vous et choisiront le meilleur plan d'exécution pour cette requête et tous les équivalents. Cela signifie que tant que deux requêtes sont logiquement identiques, elles devraient toujours générer le même plan d'exécution sur un rdbms donné.

Cela étant dit, de nombreuses requêtes sont équivalentes (même jeu de résultats) mais uniquement en raison de contraintes dont la base de données elle-même n'est pas consciente, alors faites attention à ces cas (par exemple, pour un champ indicateur avec des nombres 1-6, la base de données ne sait pas <3 Est identique à in (1,2)). Mais à la fin de la journée, si vous pensez simplement à la lisibilité des instructions and et or, cela ne fera aucune différence pour les performances de quelle manière vous les écrivez.

2
Adam Martin

Vous devrez exécuter le plan d'exécution sur les deux et voir les résultats.

Je pense qu'ils auront le même plan d'exécution car il sera exécuté de la même manière qu'un signe = Normal lorsqu'une seule valeur est placée à l'intérieur de l'instruction IN().

Il n'y a aucune raison pour que l'optimiseur se comporte différemment sur une requête comme celle-ci.

1
Yossi Orsen