10万行未満のデータセットで実行するのに最大2秒かかる次のクエリがあります。
私のSQLは非常に錆びていますが、これは必要以上に多くの作業を行っているように見えます。誰もがこれをスピードアップするためにどこを探すべきかについていくつかの指針を提供できますか?
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'
行ごとにそのようなルックアップを行う代わりに、次のようにAddressRole
およびSetting
テーブルを結合できます。
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;
これにより、実行される結合の数が減り、結果セットのカーディナリティは変更されません。
MAX
を追加してGROUP BY
を実行できるようにしました。これは、AddressRole
テーブルにAddress
テーブル。このようにして、カーディナリティをAddress
テーブルと同じものとして維持しますが、AddressRole
の行のいずれかに、以前のAddressRoleTypeID
の値が含まれているかどうかを確認できます。探している。
MAX
のない元のクエリのサブクエリが単一の行を返す場合、TOP
とGROUP BY
は必要ありません。