Question

Nous avons une requête qui exécute une table assez longue mais qui doit malheureusement utiliser LIKE '% ABC%' sur quelques champs varchar pour que l'utilisateur puisse rechercher des noms partiels, etc. SQL Server 2005

L'ajout d'un index sur ces champs varchar aiderait-il en termes de performances de requête lors de l'utilisation de LIKE ou ignore-t-il les index et effectue-t-il une analyse complète dans ces cas?

Y a-t-il d'autres moyens d'améliorer les performances lors de l'utilisation de LIKE?

Était-ce utile?

La solution

Uniquement si vous ajoutez la recherche de texte intégral à ces colonnes et utilisez les fonctionnalités de requête de texte intégral de SQL Server.

Sinon, non, un index ne vous aidera pas.

Autres conseils

Vous pouvez potentiellement voir des améliorations de performances en ajoutant un ou plusieurs index (s), cela dépend beaucoup des spécificités suivantes:)

Quelle est la taille totale de vos colonnes prédiquées dans la taille totale de la ligne? Combien de lignes comptez-vous faire correspondre? Avez-vous besoin de renvoyer toutes les lignes qui correspondent au prédicat, ou juste les 1 premières ou les n premières lignes?

Si vous recherchez des valeurs avec une sélectivité / unicité élevée (si peu de lignes à renvoyer), et que les colonnes prédiquées constituent une petite partie de la taille de la ligne entière, un index peut être très utile. Ce sera toujours une analyse, mais votre index contiendra plus de lignes par page que la table source.

Voici un exemple où la taille totale de la ligne est beaucoup plus grande que la taille de la colonne dans laquelle effectuer la recherche:

create table t1 (v1 varchar(100), b1 varbinary(8000))
go
--add 10k rows of filler
insert t1 values ('abc123def', cast(replicate('a', 8000) as varbinary(8000)))
go 10000
--add 1 row to find
insert t1 values ('abc456def', cast(replicate('a', 8000) as varbinary(8000)))
go

set statistics io on 
go
select * from t1 where v1 like '%456%'
--shows 10001 logical reads

--create index that only contains the column(s) to search across
create index t1i1 on t1(v1)
go
select * from t1 where v1 like '%456%'
--or can force to 
--shows 37 logical reads

Si vous examinez le plan d'exécution réel, vous pouvez voir que le moteur a analysé l'index et effectué une recherche de signet sur la ligne correspondante. Vous pouvez également demander à l'optimiseur d'utiliser directement l'index s'il n'a pas décidé d'utiliser ce plan seul: sélectionnez * à partir de t1 avec (index (t1i1)), où v1 ressemble à '% 456%'

Si vous devez effectuer une recherche dans plusieurs colonnes très sélectives, vous pouvez créer plusieurs index et utiliser une approche de réduction. Par exemple. Tout d'abord, déterminez un ensemble d'identifiants (ou quelle que soit votre PK) à partir de votre index hautement sélectif, puis recherchez dans vos colonnes moins sélectives avec un filtre sur ce petit jeu de PK.

Si vous devez toujours renvoyer un grand nombre de lignes, il serait certainement préférable de numériser une table.

Les optimisations possibles dépendent donc beaucoup des spécificités de la définition de votre table et de la sélectivité de vos données.

HTH! -Adrian

Le seul autre moyen d'améliorer les performances (hormis l'utilisation de l'indexation en texte intégral) consiste à utiliser "LIKE ABC%". - N'ajoutez pas le caractère générique aux deux extrémités de votre terme de recherche - dans ce cas, un index pourrait fonctionner.

Si vos besoins sont tels que vous devez avoir des caractères génériques aux deux extrémités de votre terme de recherche, vous n’avez pas de chance ...

Marc

Comme '% ABC%' effectuera toujours une analyse complète de la table. Il n'y a pas de chemin aux alentours.

Vous avez plusieurs approches alternatives. Premièrement, la recherche en texte intégral est vraiment conçue pour ce genre de problème, je vais donc commencer par le regarder.

Dans certaines circonstances, il peut également être approprié de dénormaliser les données et de pré-traiter les champs cibles en jetons appropriés, puis d’ajouter ces termes de recherche possibles dans une table de recherche distincte à plusieurs. Par exemple, si mes données consistaient toujours en un champ contenant le motif "AAA / BBB / CCC" et que mes utilisateurs effectuaient une recherche sur BBB, je le masquais lors de l'insertion / de la mise à jour (et de le supprimer lors de la suppression). Ce serait également l’un des cas où l’utilisation de déclencheurs, plutôt que du code d’application, serait préférable .

Je dois souligner que ce n'est pas vraiment une technique optimale et ne doit être utilisé que si les données correspondent bien à l'approche et pour une raison quelconque, vous ne souhaitez pas utiliser la recherche en texte intégral (et les performances de la base de données sur des supports similaires). scan est vraiment inacceptable). Il est également probable que des problèmes de maintenance surviennent plus tard.

créer des statistiques sur cette colonne. SQL Server 2005 a optimisé la recherche dans la chaîne afin que vous puissiez en tirer profit.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top