Je constate un comportement étrange avec la requête T-SQL suivante dans SQL Server 2012:
SELECT Id
FROM dbo.Person
WHERE CONTAINS(Name, '"John" AND "Smith"')
ORDER BY Name
L'exécution de cette requête seule me donne environ 1 300 résultats en moins de deux secondes (il y a un index en texte intégral sur Name
)
Cependant, lorsque je change la requête en ceci:
SELECT Id
FROM dbo.Person
WHERE CONTAINS(Name, '"John" AND "Smith"')
ORDER BY Name
OFFSET 0 rows
FETCH NEXT 10 ROWS ONLY
Il me faut plus de 20 secondes pour me donner 10 résultats.
La requête suivante est encore pire:
SELECT Id
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY Name) AS RowNum, Id
FROM dbo.Person
WHERE CONTAINS(Name, '"John" AND "Smith"') ) AS RowConstrainedResult
WHERE RowNum >= 0 AND RowNum < 11
ORDER BY RowNum
Il faut plus de 1,5 minutes pour terminer!
Des idées?
SELECT TOP 10 * .... ORDER BY Name
?Réponses:
Comme vous voulez juste que le
TOP 10
nom soit ordonné, il pense qu'il sera plus rapide de descendre l'indexname
dans l'ordre et de voir si chaque ligne correspond auCONTAINS(Name, '"John" AND "Smith"') )
prédicat.Vraisemblablement, il faut beaucoup plus de lignes pour trouver les 10 correspondances requises, puis il s'attend et ce problème de cardinalité est aggravé par le nombre de recherches de clés.
Un hack pour l' arrêter à l' aide de ce plan serait de changer
ORDER BY
àORDER BY Name + ''
bien que l' utilisationCONTAINSTABLE
en conjonction avecFORCE ORDER
devrait également fonctionner.la source
Cela ressemble à une mauvaise estimation de la sélectivité classique. Je ne sais pas ce qui peut être fait à ce sujet car le "pilote" de la requête est une recherche plein texte que vous ne pouvez pas augmenter avec des statistiques.
Essayez de réécrire le
where contains
prédicat dans uninner join containstable
( CONTAINSTABLE ) et appliquez des conseils d'ordre de jointure pour forcer la forme du plan.Ce n'est pas une solution parfaite car il a des problèmes de maintenance, mais je ne vois pas d'autre façon.
la source
J'ai réussi à résoudre le problème:
Comme je l'ai dit dans la question, il y avait des indizes sur toutes les colonnes + statistiques pour chaque colonne. (En raison des requêtes LIKE héritées), j'ai supprimé toutes les statistiques et les statistiques, ajouté la recherche en texte intégral et voilà, la requête est devenue très rapide.
Il semble que les indicateurs aient conduit à un plan d'exécution différent.
Merci beaucoup à tous pour votre aide!
la source