Verbessern Sie die Leistung der CASE-Auswahl

7

Ich habe die folgende Abfrage, die bis zu 2 Sekunden dauert, um mit einem Datensatz von weniger als 100.000 Zeilen ausgeführt zu werden.

Mein SQL ist sehr verrostet, aber es sieht so aus, als würde es eine Menge mehr Arbeit leisten, als es sollte. Kann jemand einige Hinweise geben, wo man nachsehen muss, um dies zu beschleunigen?

SELECT
    a.AddressID,
    IsPrincipal = CASE
    WHEN EXISTS(SELECT TOP 1 1 FROM dbo.Setting s WHERE s.SettingValue = a.AddressID AND s.SettingDefinitionID = 3 AND s.ProfileID = 1)
                THEN 1
                ELSE 0
            END,
    IsPickUp = CASE
                WHEN EXISTS(SELECT TOP 1 1 FROM dbo.AddressRole ar WHERE ar.AddressID = a.AddressID AND ar.[AddressRoleTypeID] = 2)
                THEN 1
                ELSE 0
            END,
    IsSender = CASE
                WHEN EXISTS(SELECT TOP 1 1 FROM dbo.AddressRole ar WHERE ar.AddressID = a.AddressID AND ar.[AddressRoleTypeID] = 3)
                THEN 1
                ELSE 0
            END,
            IsDelivery = CASE
                WHEN EXISTS(SELECT TOP 1 1 FROM dbo.AddressRole ar WHERE ar.AddressID = a.AddressID AND ar.[AddressRoleTypeID] = 4)
                THEN 1
                ELSE 0
            END,
    IsReceiver = CASE
                WHEN EXISTS(SELECT TOP 1 1 FROM dbo.AddressRole ar WHERE ar.AddressID = a.AddressID AND ar.[AddressRoleTypeID] = 5)
                THEN 1
                ELSE 0
            END
        FROM dbo.[Address] AS a
        WHERE a.MFTID = '12345'
Risma
quelle

Antworten:

7

Anstatt für jede Zeile eine solche Suche durchzuführen, können Sie die AddressRoleund Setting-Tabellen wie folgt verknüpfen:

SELECT
    a.AddressID,
    IsPrincipal = Max(iif(s.SettingValue Is Not Null, 1, 0)),
    IsPickUp = Max(iif(ar.AddressRoleTypeID = 2, 1, 0)),
    IsSender = Max(iif(ar.AddressRoleTypeID = 3, 1, 0)),
    IsDelivery = Max(iif(ar.AddressRoleTypeID = 4, 1, 0)),
    IsReceiver = Max(iif(ar.AddressRoleTypeID = 5, 1, 0))
  FROM dbo.[Address] AS a
  Left Join dbo.Setting As s
    On a.AddressID = s.SettingValue
    And s.SettingDefinitionID = 3
    And s.ProfileID = 1
  Left Join dbo.AddressRole As ar
    On a.AddressID = ar.AddressID
  WHERE a.MFTID = '12345'
  Group By a.AddressID;

Dies sollte die Anzahl der durchgeführten Verknüpfungen verringern und nicht die Kardinalität der Ergebnismenge ändern.

Ich habe das hinzugefügt, MAXdamit ich a ausführen kann GROUP BY, da ich davon ausgehe, dass es AddressRolefür jede Zeile in der AddressTabelle mehr als eine Zeile in der Tabelle gibt. Auf diese Weise behalten wir die Kardinalität bei, die mit der AddressTabelle identisch ist , aber wir können sehen, ob eine der Zeilen in dem AddressRoleden Wert enthält AddressRoleTypeID, den wir gesucht haben.

Die MAXund GROUP BYwerden nicht benötigt, wenn die Unterabfragen Ihrer ursprünglichen Abfrage ohne die TOPRückgabe einer einzelnen Zeile.

Mendosi
quelle