Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Zwei radikal unterschiedliche Abfragen für 4 Millionen Datensätze werden gleichzeitig ausgeführt - eine verwendet Brute Force

Vertrauen Sie dem Optimierer.

Schreiben Sie die Abfrage, die am einfachsten ausdrückt, was Sie erreichen möchten. Wenn Sie haben Leistungsprobleme Mit dieser Abfrage sollten Sie prüfen, ob Indizes fehlen. Aber explizit sollten Sie es trotzdem nicht müssen mit diesen Indizes arbeiten.

Kümmern Sie sich nicht um Überlegungen darüber, wie Sie könnte eine solche Suche implementieren.

In sehr In seltenen Fällen müssen Sie möglicherweise die Abfrage weiter zwingen, bestimmte Indizes zu verwenden (über Hinweise), aber dies sind wahrscheinlich <0,1 % der Abfragen.

In Ihren geposteten Plänen verursacht Ihre "optimierte" Version Scans gegen 2 Indizes Ihrer (ich nehme an) Params-Tabelle (PK_Params_1, IX_Params_1). Ohne die Abfragen zu sehen, ist es schwierig zu wissen, warum dies geschieht, aber wenn Sie mit einem einzelnen Scan gegen eine Tabelle ("Brute Force") und zwei vergleichen, ist es leicht zu erkennen, warum der zweite nicht effizienter ist.

Ich denke, ich würde versuchen:

        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]

D.h. einen Anti-Join einführen, der die unerwünschten Ergebnisse eliminiert.