Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Deux requêtes radicalement différentes sur des enregistrements de 4 millions de dollars s'exécutent en même temps - l'une utilise la force brute

Faites confiance à l'optimiseur.

Écrivez la requête qui exprime le plus simplement ce que vous essayez d'accomplir. Si vous rencontrez des problèmes de performances avec cette requête, alors vous devriez regarder s'il y a des index manquants. Mais vous ne devriez toujours pas avoir à explicitement travailler avec ces index.

Ne vous préoccupez pas de la façon dont vous pourrait implémenter une telle recherche.

Dans très Dans de rares cas, vous devrez peut-être forcer davantage la requête à utiliser des index particuliers (via des conseils), mais cela représente probablement < 0,1 % des requêtes.

Dans vos plans publiés, votre version "optimisée" provoque des analyses contre 2 index de votre table Params (je présume) (PK_Params_1, IX_Params_1). Sans voir les requêtes, il est difficile de savoir pourquoi cela se produit, mais si vous comparez avec une seule analyse par rapport à une table ("Force brute") et deux, il est facile de voir pourquoi la seconde n'est pas plus efficace.

Je pense que j'essaierais :

        SELECT      p.ProductID, ptr.[Rank]
        FROM        dbo.SearchItemsGet(@SearchID, NULL) AS si
                    JOIN dbo.ProductDefs AS pd
        ON          pd.ParamTypeID = si.ParamTypeID
                    JOIN dbo.Params AS p
        ON          p.ProductDefID = pd.ProductDefID
                    JOIN dbo.ProductTypesResultsGet(@SearchID) AS ptr
        ON          ptr.ProductTypeID = pd.ProductTypeID

LEFT JOIN Params p_anti
    on p_anti.ProductDefId = pd.ProductDefID and
         (p_anti.ParamLo < si.LowMin or p_anti.ParamHi > si.HiMax)


        WHERE       si.Mode IN (1, 2)

AND p_anti.ProductID is null

        GROUP BY    p.ProductID, ptr.[Rank]

C'est à dire. introduisez un anti-jointure qui élimine les résultats que vous ne voulez pas.