2010-03-28 6 views
3

J'ai une requête qui recherche des clients en utilisant "like" avec wildcard. Par exemple:SQL Server: comment optimiser les requêtes "like"?

SELECT TOP (10) 
     [t0].[CLIENTNUMBER], 
     [t0].[FIRSTNAME], 
     [t0].[LASTNAME], 
     [t0].[MI], 
     [t0].[MDOCNUMBER] 
    FROM [dbo].[CLIENT] AS [t0] 
WHERE (LTRIM(RTRIM([t0].[DOCREVNO])) = '0') 
    AND ([t0].[FIRSTNAME] LIKE '%John%') 
    AND ([t0].[LASTNAME] LIKE '%Smith%') 
    AND ([t0].[SSN] LIKE '%123%') 
    AND ([t0].[CLIENTNUMBER] LIKE '%123%') 
    AND ([t0].[MDOCNUMBER] LIKE '%123%') 
    AND ([t0].[CLIENTINDICATOR] = 'ON') 

Il peut également utiliser moins de paramètres dans « where », par exemple:

SELECT TOP (10) 
     [t0].[CLIENTNUMBER], 
     [t0].[FIRSTNAME], 
     [t0].[LASTNAME], 
     [t0].[MI], 
     [t0].[MDOCNUMBER] 
    FROM [dbo].[CLIENT] AS [t0] 
WHERE (LTRIM(RTRIM([t0].[DOCREVNO])) = '0') 
    AND ([t0].[FIRSTNAME] LIKE '%John%') 
    AND ([t0].[CLIENTINDICATOR] = 'ON') 

Quelqu'un peut-il dire quelle est la meilleure façon d'optimiser les performances de cette requête? Peut-être que je dois créer un index? Cette table peut avoir jusqu'à 1000 000 enregistrements en production.

+0

L'index ne vous aidera pas si vous utilisez 'LIKE'. Et pourquoi avez-vous besoin d'optimiser: avez-vous déjà un problème de performance? – van

+3

Les index ne peuvent pas vous aider avec des valeurs commençant par des caractères génériques, c'est-à-dire qu'ils vous aideront avec des valeurs comme 'John%' mais ** not ** '% John%' – vladr

+0

Si vous utilisez LINQ, vous pouvez passer de 'Contains' à 'StartsWith', SQL Server pourra utiliser un index. – Gabe

Répondre

7

faire beaucoup pour un LIKE où le motif a la forme '%XXX%', vous voulez regarder la capacité d'indexation de texte intégral de SQL Server et utiliser CONTAINS au lieu de LIKE. En l'état, vous effectuez une analyse de table complète, car un index normal n'aidera pas la recherche d'un élément qui commence par un caractère générique, mais un index de texte intégral le sera.

/* ... */ 
WHERE (LTRIM(RTRIM([t0].[DOCREVNO])) = '0') 
    AND (contains([t0].[FIRSTNAME], 'John')) 
    AND (contains([t0].[LASTNAME], 'Smith')) 
    AND (contains([t0].[SSN], '123')) 
    AND (contains([t0].[CLIENTNUMBER],'123')) 
    AND (contains([t0].[MDOCNUMBER], '123')) 
    AND ([t0].[CLIENTINDICATOR] = 'ON') 
+0

Est-ce que cela trouvera une personne dont le SSN est '567-89-0123'? – Gabe

+1

+1, sauf que vous n'indiquez pas si les index de texte intégral sont mis à jour sur une planification (de manière asynchrone) par opposition à "sur insertion/mise à jour/suppression" (de manière synchrone) – vladr

+0

@Gabe - En supposant que les autres critères de filtrage vrai, oui. Il trouvera également 123-45-6789, 678-90-1234 et même 012-34-5678 si le SSN est stocké sans les tirets. – Thomas

0
+0

Juste pour ajouter à MSSQL: approche changée entre 2005 et 2008 https://www.red-gate.com/simple-talk/sql/learn-sql-server/understanding-full-text-indexing-in-sql-server / – MaLiN2223

Questions connexes