web-dev-qa-db-fra.com

SQL 'like' vs '=' performance

Cette question contourne ce que je me demande, mais les réponses ne répondent pas exactement à cela.

Il semblerait que en général '=' est plus rapide que 'like' lorsque vous utilisez des caractères génériques. Cela semble être la sagesse conventionnelle. Cependant, supposons que je dispose d'une colonne contenant un nombre limité d'identifiants varchar fixes, codés en dur, et que je souhaite sélectionner toutes les lignes correspondant à l'un d'entre eux:

select * from table where value like 'abc%'

et

select * from table where value = 'abcdefghijklmn'

'Like' devrait seulement tester les trois premiers caractères pour trouver une correspondance, alors que '=' doit comparer la chaîne entière. Dans ce cas, il me semble que "comme" aurait un avantage, toutes choses égales par ailleurs.

Ceci est conçu comme une question académique générale et ne devrait donc pas importer quelle base de données, mais cela est apparu avec SQL Server 2005.

72
mickeyf

Voir http://myitforum.com/cs2/blogs/jnelson/archive/2007/11/16/108354.aspx

Citation de là:

les règles d'utilisation d'index avec LIKE ressemblent à ceci:

  • Si votre critère de filtre utilise la valeur égal à = et que le champ est indexé, il utilisera probablement une recherche INDEX/CLUSTERED INDEX.

  • Si vos critères de filtre utilisent LIKE, sans caractères génériques (comme si vous aviez un paramètre dans un rapport Web POUVANT avoir un% mais que vous utilisiez plutôt la chaîne complète), il est presque aussi probable que # 1 d'utiliser l'index. L'augmentation du coût est presque rien.

  • Si vos critères de filtre utilisent LIKE, mais avec un caractère générique au début (comme dans Name0 LIKE '% UTER'), il est beaucoup moins probable que l'index soit utilisé, mais il est toujours possible d'effectuer un INDEX SCAN sur une plage complète ou partielle de l'index.

  • CEPENDANT, si votre critère de filtre utilise LIKE, mais commence par un STRING FIRST et contient des caractères génériques quelque part APRÈS (comme dans Name0 LIKE 'COMP% ER'), SQL peut simplement utiliser une RECHERCHE INDEX pour rechercher rapidement les lignes qui ont le même caractères de départ, puis regardez à travers ces lignes pour une correspondance exacte.

(N'oubliez pas également que le moteur SQL peut ne pas utiliser l'index comme vous le souhaiteriez, en fonction de ce qui se passe dans votre requête et des tables auxquelles vous vous connectez. Le moteur SQL se réserve le droit de réécrire votre interroger un peu pour obtenir les données de la manière qui lui semble la plus efficace et qui peut inclure un INDEX SCAN au lieu d'une INDEX SEEK)

56
BonyT

C'est une différence mesurable.

Exécutez ce qui suit:

Create Table #TempTester (id int, col1 varchar(20), value varchar(20))
go

INSERT INTO #TempTester (id, col1, value)
VALUES
(1, 'this is #1', 'abcdefghij')
GO

INSERT INTO #TempTester (id, col1, value)
VALUES
(2, 'this is #2', 'foob'),
(3, 'this is #3', 'abdefghic'),
(4, 'this is #4', 'other'),
(5, 'this is #5', 'zyx'),
(6, 'this is #6', 'zyx'),
(7, 'this is #7', 'zyx'),
(8, 'this is #8', 'klm'),
(9, 'this is #9', 'klm'),
(10, 'this is #10', 'zyx')
GO 10000

CREATE CLUSTERED INDEX ixId ON #TempTester(id)CREATE CLUSTERED INDEX ixId ON #TempTester(id)

CREATE NONCLUSTERED INDEX ixTesting ON #TempTester(value)

Ensuite:

SET SHOWPLAN_XML ON

Ensuite:

SELECT * FROM #TempTester WHERE value LIKE 'abc%'

SELECT * FROM #TempTester WHERE value = 'abcdefghij'

Le plan d’exécution qui en résulte vous montre que le coût de la première opération, la comparaison LIKE, est environ 10 fois plus cher que le = Comparaison.

Si vous pouvez utiliser un = _ comparaison, veuillez le faire.

38
JNK

Vous devez également garder à l’esprit que lorsqu’on utilise like, certaines versions de SQL ignorent les index, ce qui nuit aux performances. Cela est particulièrement vrai si vous n'utilisez pas le modèle "commence par" comme dans votre exemple.

Vous devriez vraiment regarder le plan d'exécution de la requête et voir ce qu'il fait, devinez le moins possible.

Ceci étant dit, le modèle "commence par" peut et est optimisé dans SQL Server. Il va utiliser l'index de la table. EF 4.0 est passé à like pour StartsWith pour cette raison même.

13
Blindy

Si value n'est pas indexé, les deux résultats sont analysés. La différence de performance dans ce scénario sera négligeable.

Si value est indexé, comme le souligne Daniel dans son commentaire, le = se traduira par une recherche dans l’index correspondant aux performances O (journal N). LIKE entraînera (très probablement - en fonction de sa sélectivité) un balayage partiel de l'index >= 'abc' et < 'abd' qui nécessitera plus d’efforts que le =.

Notez que je parle de SQL Server ici - tous les SGBD ne seront pas sympas avec LIKE.

7
Will A

Vous posez la mauvaise question. Dans les bases de données, ce n'est pas la performance de l'opérateur qui compte, mais toujours SARGability de l'expression et couvrabilité de la requête globale. Les performances de l'opérateur lui-même sont en grande partie hors de propos.

Alors, comment faire LIKE et = comparer en termes de SARGability? LIKE, lorsqu'il est utilisé avec une expression qui ne commence pas par une constante (par exemple, lorsqu'il est utilisé LIKE '%something') est par définition non-SARGabale. Mais est-ce que cela fait = ou LIKE 'something%' SARGable? Comme pour toute question sur les performances SQL, la réponse ne réside pas dans la requête du texte, mais dans le schéma déployé. Ces expressions peut être SARGable si un index existe pour les satisfaire.

Donc, à vrai dire, il y a de petites différences entre = et LIKE. Mais demander si un opérateur ou un autre opérateur est "plus rapide" en SQL revient à demander "Qu'est-ce qui va plus vite, une voiture rouge ou une voiture bleue?". Vous devriez poser des questions sur la taille du moteur et le poids du véhicule, et non sur la couleur ... Pour aborder les questions relatives à l'optimisation des tables relationnelles, l'emplacement à consulter est constitué par vos index et vos expressions dans la clause WHERE (et d'autres clauses, mais cela commence généralement par le WHERE).

5
Remus Rusanu

Un exemple personnel utilisant mysql 5.5: j'avais une jointure interne entre 2 tables, une de 3 millions de lignes et une de 10 000 lignes.

Lorsque vous utilisez un objet similaire sur un index comme ci-dessous (aucun caractère générique), cela prend environ 30 secondes:

where login like '12345678'

en utilisant 'expliquer' je reçois:

enter image description here

Lorsque vous utilisez un '=' sur la même requête, cela prend environ 0,1 seconde:

where login ='600009'

En utilisant 'expliquer' je reçois:

enter image description here

Comme vous pouvez le constater, le like a complètement annulé la recherche dans l'index. La requête a donc pris 300 fois plus de temps.

4
Aris

Peut-être que vous cherchez à propos de Recherche en texte intégral .

Contrairement à la recherche en texte intégral, le prédicat LIKE Transact-SQL fonctionne uniquement sur les modèles de caractères. De même, vous ne pouvez pas utiliser le prédicat LIKE pour interroger des données binaires formatées. En outre, une requête LIKE sur une grande quantité de données textuelles non structurées est beaucoup plus lente qu'une requête en texte intégral équivalente sur les mêmes données . Une requête similaire sur des millions de lignes de données texte peut prendre plusieurs minutes. tandis qu'une requête en texte intégral ne peut prendre que quelques secondes ou moins par rapport aux mêmes données, en fonction du nombre de lignes renvoyées.

0
user586399