Warum erzwingt das Referenzieren einer Variablen in einem Join-Prädikat verschachtelte Schleifen?


16

Ich bin kürzlich auf dieses Problem gestoßen und konnte online keine Diskussion darüber finden.

Die Abfrage unten

DECLARE @S VARCHAR(1) = '';

WITH T
     AS (SELECT name + @S AS name2,
                *
         FROM   master..spt_values)
SELECT *
FROM   T T1
       INNER JOIN T T2
         ON T1.name2 = T2.name2;

Erhält immer einen verschachtelten Schleifenplan

Bildbeschreibung hier eingeben

Der Versuch, das Problem mit INNER HASH JOINoder INNER MERGE JOINHinweise zu erzwingen, erzeugt den folgenden Fehler.

Der Abfrageprozessor konnte aufgrund der in dieser Abfrage definierten Hinweise keinen Abfrageplan erstellen. Senden Sie die Abfrage erneut, ohne Hinweise anzugeben und ohne SET FORCEPLAN zu verwenden.

Ich habe eine Problemumgehung gefunden, mit der Hash- oder Merge-Joins verwendet werden können - das Umschließen der Variablen in ein Aggregat. Der generierte Plan ist deutlich kostengünstiger (19.2025 vs 0.261987)

DECLARE @S2 VARCHAR(1) = '';

WITH T
     AS (SELECT name + (SELECT MAX(@S2)) AS name2,
                *
         FROM   spt_values)
SELECT *
FROM   T T1
       INNER JOIN T T2
         ON T1.name2 = T2.name2; 

Bildbeschreibung hier eingeben

Was ist der Grund für dieses Verhalten? und gibt es einen besseren Workaround als den, den ich gefunden habe? (das erfordert möglicherweise nicht die zusätzlichen Ausführungsplanverzweigungen)

Antworten:


13

Ich habe versucht, Ihre Abfrage auf einer SQL 2012-Instanz und Trace-Flag 4199 scheint das Problem zu beheben. Wenn diese Option aktiviert ist, erhalte ich einen Merge-Join für insgesamt 0,24 und keinen der zusätzlichen Zweige.

Der spezifische KB-Artikel für dieses Problem lautet: Leistungsprobleme treten auf, wenn das Verknüpfungsprädikat in Ihrer Abfrage äußere Referenzspalten in SQL Server 2005 oder SQL Server 2008 enthält

Bildbeschreibung hier eingeben

Zur weiteren Qualifizierung aktiviert TF 4199 alle Optimierungskorrekturen. Weitere Informationen finden Sie unter diesem Link . Wenn Sie alles auf einmal aktivieren, kann dies seltsame Nebenwirkungen haben. Wenn Sie also einen bestimmten Fix finden, ist es möglicherweise besser, den Fix selbst zu aktivieren.

Sie können ein Ablaufverfolgungsflag auf Abfragebasis aktivieren, indem Sie Folgendes verwenden OPTION (QUERYTRACEON 4199):


0

Alte Frage, aber als ich die Antwort sah, war das nicht eindeutig. Ich dachte, ich würde eine Problemumgehung veröffentlichen, die ich gefunden habe. HASHIch bin mir nicht sicher, warum das Abfrageoptimierungsprogramm blockiert , aber ich denke, es gefällt nicht, MERGEweil es keine sortierte Eingabe hat. 2012/14

DECLARE @S VARCHAR(1) = '';

    WITH T
        AS (SELECT TOP (2147483647)
                name + @S AS name2,
                *
            FROM   master..spt_values
            ORDER BY name + @S)
    SELECT *
    FROM   T T1
           INNER JOIN T T2
             ON T1.name2 = T2.name2;

erstellt folgenden Plan:

Bildbeschreibung hier eingeben

Forcen TOPund das ORDER BYin der CTE scheint dem Optimierer genügend Wissen über den Datensatz zu geben, um das auszuführen MERGE JOIN.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.