In a SQL Server 2008R2 sproc, I have the following code to calculate the total number of records returned by a dynamic query:
-- count the actual number of results
DECLARE @rowcount TABLE (Value int);
INSERT INTO @rowcount
EXEC('SELECT COUNT(*) ' + @sqlBody);
SELECT @varcharActualNumResults = VALUE FROM @rowcount;
The dynamic query is broken up into three parts: @sqlTop, @sqlBody, and @sqlBottom.
I want to know how many records are actually returned by @sqlBody, but the actual execution is the concatenated @sqlTop + @sqlBody + @sqlBottom.
The issue is that the above query takes 24136ms (roughly 24 seconds) where the actual number of records is around 18,000.
Another issue comes up where I want to get the rowcount for the entire query:
EXEC (@sqlTop + @sqlBody + @sqlBottom)
SET @NumberOfResultsReturned = @@ROWCOUNT;
This execution takes roughly two seconds.
Here is a sample query:
SELECT TOP(10) Title
FROM ItemData
WHERE (
FREETEXT(Title, '"windshield"')
OR
( [Title] LIKE '%mazda 6%' )
)
AND ( WebsiteID=1 )
ORDER BY DateAdded DESC
@sqlBody contains everything between the FROM and before ORDER BY.
How can this be optimized?
UPDATE
In my sproc I defined my temp table then attempt to populate it through the EXEC command. However at the EXEC command line I’m getting an error indicating the temp table has to be defined:
DECLARE @Temp_Results TABLE (ItemListID BIGINT, Title VARCHAR(255) )
EXEC ('INSERT INTO @Temp_Results (ItemListID, Title) (' + @sqlTop + @sqlBody + ')')
If I take out the exec command and execute the SQL it works fine. How can I get around this?
I understand your problem now and I think the best way is to not use a dynamic query. However, if you have to use the dynamic query here are some ways to speed it up.
Make sure all the items in the where have indexes.
Add your counting into the EXEC so that the row count is returned with one exec call. For example in your dynamic query put the results of the reduction in a temp table and count that table then select from that table.