Reputation: 45096
Building up a query.
The single query is shown below and runs in 7.0 seconds. It does return the correct answer. Need to count rows based on certain conditions and then get the maximum count. My problem is performance of this stand along query. That same query wrapped in a cursor is 0.15 seconds. In the cursor the query plan is much different. How can I make the stand alone query run faster?
Using hints was able to get the stand alone to plan to look like the cursor plan and that fixed the speed problem.
Fixed query: (not all the way fixed as OPTION fails)
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;
problem query:
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
I also need to run that single query against multiple values and put it in a cursor with a loop. I know cursor is bad but I could not figure out how to do it without a cursor.
The query stand alone and inside the loop both return the same correct answer.
My surprise is the exact same query inside a cursor loop is 40 times faster.
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
Upvotes: 3
Views: 4649
Reputation: 45096
Using hints was able to get the stand alone to plan to look like the cursor plan and that fixed the speed problem.
Fixed query: (not all the way fixed as OPTION fails)
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;
Upvotes: 1