クエリの作成。
1 つのクエリを以下に示します。実行時間は 7.0 秒です。正しい答えを返します。特定の条件に基づいて行をカウントし、最大数を取得する必要があります。私の問題は、このスタンド アロング クエリのパフォーマンスです。カーソルでラップされた同じクエリは 0.15 秒です。カーソルでは、クエリ プランが大きく異なります。スタンドアロン クエリをより高速に実行するにはどうすればよいですか?
ヒントを使用すると、スタンドアローンをカーソル プランのように見せることができ、速度の問題が修正されました。
修正されたクエリ: (OPTION が失敗するため、完全には修正されていません)
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [docSVenum1] with (nolock)
INNER LOOP JOIN [FTSindexWordOnce] as w1 with (NOLOCK, FORCESEEK)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER HASH JOIN [FTSindexWordOnce] as w2 with (NOLOCK)
ON w1.wordID = w2.wordID and w2.[sID] = '2'
GROUP BY W1.[sID]
-- OPTION (HASH GROUP)
) as list;
問題のクエリ:
select getdate();
go
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [FTSindexWordOnce] as w1 with (nolock)
INNER JOIN [docSVenum1] with (nolock)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER JOIN [FTSindexWordOnce] as w2 with (nolock)
ON w1.wordID = w2.wordID AND w2.[sID] = '2'
GROUP BY W1.[sID]
) as list;
go
select getdate(); -- 7.0 seconds
また、その単一のクエリを複数の値に対して実行し、ループを使用してカーソルに配置する必要もあります。カーソルが悪いことは知っていますが、カーソルなしでそれを行う方法がわかりませんでした。
クエリは単独でもループ内でも同じ正解を返します。
驚いたことに、カーソル ループ内のまったく同じクエリが 40 倍高速です。
DECLARE @sid int
DECLARE sID_cursor CURSOR FOR
SELECT top 80 sID
FROM docSVsys
WHERE sID = '2' -- actually I want to not have this and let it loop through all
-- when i built the loop i saw performance improvement
ORDER BY sID
OPEN sID_cursor
FETCH NEXT FROM sID_cursor
INTO @sID
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @sID
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [FTSindexWordOnce] as w1 with (nolock)
INNER JOIN [docSVenum1] with (nolock)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER JOIN [FTSindexWordOnce] as w2 with (nolock)
ON w1.wordID = w2.wordID AND w2.[sID] = @sID
GROUP BY W1.[sID]
) as list
FETCH NEXT FROM sID_cursor
INTO @sID
END
CLOSE sID_cursor;
DEALLOCATE sID_cursor;
go
select getdate(); -- 0.15 seconds