2011-05-10 1 views
3

Version: SQL Server 2008 R2Get SQL Server pour utiliser recherche d'index + recherche clé au lieu de scan index ordonné en clusters, sans WITH (FORCESEEK)

Base de données: AdventureWorks 2008R2 de http://msftdbprodsamples.codeplex.com/releases/view/55926

Requête:

SELECT TOP 10 
    * 
FROM 
    Person.Person --WITH (FORCESEEK) 
WHERE 
    LastName like 'Max%' 
    OR EXISTS (
     SELECT 
      1 
     FROM 
      Person.PersonPhone 
     WHERE 
      Person.PersonPhone.BusinessEntityID = Person.Person.BusinessEntityID 
      AND Person.PersonPhone.PhoneNumber LIKE '122%' 
    ) 
ORDER BY Person.Person.BusinessEntityID DESC 


Sans aucune indication de requête, SQL Server utilisera scan index ordonné en clusters, qui est IO intensive:

Table 'PersonPhone'. Scan count 14170, logical reads 28446, physical reads 15, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'Person'. Scan count 1, logical reads 2844, physical reads 3, read-ahead reads 3215, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 


Avec l'indicateur de requête WITH (FORCESEEK), SQL Server opter pour recherche d'index + recherche clé, qui complète plus rapide et est 500x plus respectueux de l'IO:

Table 'Person'. Scan count 1, logical reads 59, physical reads 22, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'PersonPhone'. Scan count 1, logical reads 2, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 


Ma question est, est-il façon d'obtenir SQL Server pour utiliser le meilleur plan sans aucun indice de requête? Ajout d'index peut-être? Ou changer les paramètres de configuration? Ou l'optimiseur de requêtes de SQL Server est-il complètement désemparé?

Voici un petit bijou de http://msdn.microsoft.com/en-us/library/bb510478.aspx:

règles d'optimisation des requêtes et une mauvaise estimation de cardinalité peut également provoquer l'optimiseur d'effectuer un plutôt qu'un index opération d'analyse de table ou de recherche d'index lorsqu'une requête utilise IN ou De même que la recherche prédicats.

+1

SQL Server va paramétrer automatiquement certaines requêtes - je ne connais pas les détails, cependant, il se peut que ce soit en essayant d'optimiser ce qui précède pour des valeurs LIKE ... et en tant que tel, c'est un mauvais choix de plan pour cela recherche particulière. –

+0

@marc_s, Si vous lisez la question, vous pouvez voir que sans aucun indice de requête, l'optimiseur de requête choisira le plan qui nécessite 500x plus d'E/S. Peut-être a-t-il détecté que mon disque tournait au ralenti et aspirait au travail? Cela pourrait être une bonne raison. Quoi qu'il en soit, en supposant que vous ayez relu la question, vous pouvez voir que je demandais un moyen d'aider l'optimiseur de requêtes à choisir le meilleur plan sans FORCESEEK. – sayap

+0

Je ne pense pas que SQL Server se penchera sur le matériel et décidera qu'un plan particulier est bon parce que le matériel est actuellement _ ralenti - la création de plan coûte cher. ressources - et les plans sont souvent créés en pensant à la réutilisation. –

Répondre

3

Voici une version qui présente des chiffres d'IO «décents» sans avoir recours au FORCESEEK. Il est intéressant que cette requête horrible semble «meilleur».

AVERTISSEMENT: Cela peut effectuer mieux pour « Max% » et « 122% », mais comment il va effectuer si le plan est réutilisé pour « M% » et « % » est une autre affaire ...

SELECT TOP 10 * 
FROM Person.Person P 
INNER JOIN (
SELECT BusinessEntityID 
FROM Person.Person --WITH (FORCESEEK) 
WHERE LastName like 'Max%'  

UNION 

SELECT BusinessEntityID 
FROM Person.Person --WITH (FORCESEEK) 
WHERE EXISTS (  SELECT   *  FROM   
    Person.PersonPhone  WHERE   Person.PersonPhone.BusinessEntityID = Person.Person.BusinessEntityID   AND Person.PersonPhone.PhoneNumber LIKE '122%' ) 
) NOTNICE 
ON NOTNICE.BusinessEntityID = P.BusinessEntityID 
ORDER BY P.BusinessEntityID DESC 
+0

Merci, cela fonctionne. Malheureusement, ce n'est pas très "ORM-friendly". – sayap

+1

Eh bien, avec SQLAlchemy, il n'y a pas de "non-ORM-friendly". J'ai implémenté ceci avec succès. Merci encore pour la réponse. – sayap

Questions connexes