Hi All,
I have inherited a stored procedure that forms the datasource for a linked subreport in MS Reporting Services 2005.
I have spent the best part of the weekend optimising this to improve the execution speed. It currently is taking 195ms to execute the query of the subreport, with the subreport taking 555ms to compile, with 2 values for the sample id, and a maximum of 10 rows being returned.
Any advice and/or observations would be greatly appreciated.
USE [HPLCData]
GO
/****** Object: StoredProcedure [dbo].[pr_HPLCRawData] Script Date: 08/30/2009 21:03:02 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[pr_HPLCRawData]
@maxcol int = 5,
@sampleId int,
@samplesql varchar(8000) output
AS
BEGIN
-- Create a temporary table populated by results for a given sampleId, and given a max number of columns
-- construct an output @samplesql string to query this table of the form:
-- Select SampleId, Summary, Col1, Col2, Col3, Col4, Col5 from ##tmp_results_table union all Select SampleId, Summary, Col6, Col7, Col8, Col9, Col10 from ##tmp_results_table union all Select ... etc ... from ##tmp_results_table union all Select SampleId, Summary, Col51, Col52,' ' as Col52,' ' as Col52,' ' as Col52 from ##tmp_results_table
--
Declare @sql1 varchar(8000)
Declare @sql2 varchar(8000)
Declare @sql2b varchar(8000)
Declare @sql2c varchar(8000)
Declare @sql2d varchar(8000)
Declare @sql3 varchar(8000)
Declare @sql4 varchar(8000)
Declare @sql5a varchar(8000)
Declare @sql5b varchar(8000)
Declare @sql5c varchar(8000)
Declare @sql5d varchar(8000)
Declare @sql6 varchar(8000)
Declare @query1a varchar(8000)
Declare @query1b varchar(8000)
Declare @query1c varchar(8000)
Declare @query1d varchar(8000)
Declare @query2 varchar(8000)
Declare @query2b1 varchar(8000)
Declare @query2b2 varchar(8000)
Declare @query2b3 varchar(8000)
Declare @query2b4 varchar(8000)
Declare @query2b5 varchar(8000)
Declare @query3 varchar(8000)
Declare @query3b1 varchar(8000)
Declare @query3b2 varchar(8000)
Declare @query3b3 varchar(8000)
Declare @query3b4 varchar(8000)
Declare @query3b5 varchar(8000)
Declare @query4 varchar(8000)
Declare @query4b1 varchar(8000)
Declare @query4b2 varchar(8000)
Declare @query4b3 varchar(8000)
Declare @query4b4 varchar(8000)
Declare @query4b5 varchar(8000)
Declare @query5a varchar(8000)
Declare @query5b varchar(8000)
Declare @query5b2 varchar(8000)
Declare @query5b3 varchar(8000)
Declare @query5b4 varchar(8000)
Declare @query5c varchar(8000)
Declare @sqlline varchar(8000)
Declare @lines int
Declare @line int
DECLARE @max_nbr_cols int
DECLARE @counter int
--Drop temporary tables
if exists(select * from tempdb.information_schema.tables where table_name = '##tmp_pivot_table')
drop table ##tmp_pivot_table
if exists(select * from tempdb.information_schema.tables where table_name = '##tmp_results_table')
drop table ##tmp_results_table
--Retrieve the total number of elements in a sample
SELECT @max_nbr_cols = COUNT(*) FROM elementlines l WHERE l.sampleid = @sampleId
-- if there is no data for this section, return an empty string
IF NOT @max_nbr_cols > 0
BEGIN
set @samplesql = ''
return
END
--Dynamically build queries to create ##tmp_pivot_table and ##tmp_results_table
SET @sqlline = 'Col1 varchar(20) NULL'
SET @counter = 2
WHILE @counter <= @max_nbr_cols
BEGIN
SET @sqlline = @sqlline + ',Col' + CONVERT(varchar, @counter) + ' varchar(20) NULL'
SET @counter = @counter + 1
END
SET @sql5a = 'CREATE TABLE ##tmp_pivot_table ( ' + @sqlline + ')'
SET @sql6 = 'CREATE TABLE ##tmp_results_table (SampleId int NULL, Summary varchar(50) NULL, ' + @sqlline + ')'
EXEC(@sql5a) -- creates the ##tmp_pivot_table
--Retrieve the total number of elements in a sample
SET @lines = @max_nbr_cols
SET @sql5a = 'INSERT INTO ##tmp_pivot_table SELECT MAX(CASE lineindex WHEN 1 THEN field1 ELSE '''' END) AS Col1'
SET @sql5b = ''
SET @sql5c = ''
SET @sql5d = ''
SET @sqlline = ''
SET @counter = 2
WHILE @counter <= @max_nbr_cols
BEGIN
SET @sqlline = ',MAX(CASE lineindex WHEN ' + CONVERT(varchar, @counter) + ' THEN field1 ELSE '''' END) AS Col' + CONVERT(varchar, @counter)
if(len(@sql5a) < 7600)
SET @sql5a = @sql5a + @sqlline
else if(len(@sql5b) < 7600)
SET @sql5b = @sql5b + @sqlline
else if(len(@sql5c) < 7600)
SET @sql5c = @sql5c + @sqlline
else if(len(@sql5d) < 7600)
SET @sql5d = @sql5d + @sqlline
SET @counter = @counter +1
END
SET @sql5d = @sql5d + ' FROM (Select l.lineIndex,l.elementname as field1 From elementlines l
Where l.sampleid = ' + cast(@sampleId as varchar(50)) + ') as t'
SET @sql5d = @sql5d + ' SELECT ' + cast(@sampleId as varchar(50)) + ' as SampleId, ''Element/Wavelength'' as Summary,* FROM ##tmp_pivot_table '
-- Retrieve average of repeats
Select @sql1 = 'Select ' + cast(@sampleId as varchar(50)) + ' as SampleId, ''Avg. of Repeats:'' as ''Summary''' + char(10)
Select @sql2 = ',MAX(CASE lineindex WHEN 1 THEN field1 ELSE '''' END) AS Col1' + char(10)
Select @sql2b = ''
Select @sql2c = ''
Select @sql2d = ''
select @sqlline = ''
Select @line = 2
while(@line <= @lines)
begin
SET @sqlline = ',MAX(CASE lineindex WHEN ' + CONVERT(varchar, @line) + ' THEN field1 ELSE '''' END) AS Col' + CONVERT(varchar, @line) + char(10)
if(len(@sql2) < 7600)
select @sql2 = @sql2 + @sqlline
else if(len(@sql2b) < 7600)
select @sql2b = @sql2b + @sqlline
else if(len(@sql2c) < 7600)
select @sql2c = @sql2c + @sqlline
else if(len(@sql2d) < 7600)
select @sql2d = @sql2d + @sqlline
select @line = @line + 1
end
Select @sql3 = 'From (Select s.lineIndex,
RTRIM(s.FailFlags_IR) COLLATE database_default+char(32)+(CASE WHEN RTRIM(s.FailFlags_IR) COLLATE database_default IN (''*'', ''^'', ''?'',''Z'', ''P'', ''D'',''N'') THEN ''*****'' ELSE CONVERT(varchar,s.averageresult_ir) END) AS field1
From tbloutputmoderesultstats s
Where s.sampleid = ' + cast(@sampleId as varchar(50)) + ') as t'
Select @query2 = @sql1
Select @query2b1 = @sql2
Select @query2b2 = @sql2b
Select @query2b3 = @sql2c
Select @query2b4 = @sql2d
Select @query2b5 = @sql3
--Retrieve Standard deviation
Select @sql1 = 'Select ' + cast(@sampleId as varchar(50)) + ' as SampleId, ''Std Dev:'' as ''Summary''' + char(10)
Select @sql3 = 'From (Select s.lineIndex,
(CASE WHEN RTRIM(s.FailFlags_IR) COLLATE database_default IN (''*'', ''^'', ''?'',''Z'', ''P'', ''D'',''N'') THEN ''----'' ELSE CONVERT(varchar,s.standarddeviation_ir) END) AS field1
From tbloutputmoderesultstats s
Where s.sampleid = ' + cast(@sampleId as varchar(50)) + ') as t'
Select @query3 = char(10) + 'Union All' + char(10) + @sql1
Select @query3b1 = @sql2
Select @query3b2 = @sql2b
Select @query3b3 = @sql2c
Select @query3b4 = @sql2d
Select @query3b5 = @sql3
--Retrieve percentage RSD
Select @sql1 = 'Select ' + cast(@sampleId as varchar(50)) + ' as SampleId, ''%RSD:'' as ''Summary''' + char(10)
Select @sql3 = 'From (Select s.lineIndex,
(CASE WHEN RTRIM(s.FailFlags_IR) COLLATE database_default IN (''*'', ''^'', ''?'',''Z'', ''P'', ''D'',''N'') THEN ''----'' ELSE CONVERT(varchar,s.percentrsd_ir) END) AS field1
From tbloutputmoderesultstats s
Where s.sampleid = ' + cast(@sampleId as varchar(50)) + ') as t'
Select @query4 = char(10) + 'Union All' + char(10) + @sql1
Select @query4b1 = @sql2
Select @query4b2 = @sql2b
Select @query4b3 = @sql2c
Select @query4b4 = @sql2d
Select @query4b5 = @sql3
--Retrieve repeat information
Select @sql1 = 'Select ' + cast(@sampleId as varchar(50)) + 'AS SampleId, ''Repeat:'' + cast(exposurenumber as varchar(10)) as ''Summary''' + char(10)
Select @sql3 = 'From (Select m.lineindex,m.exposurenumber,
(CASE WHEN RTRIM(m.FailFlag_IR) COLLATE database_default IN (''*'', ''^'', ''?'',''Z'', ''P'', ''D'',''N'') THEN RTRIM(m.FailFlag_IR) COLLATE database_default+char(32)+''----'' ELSE CONVERT(varchar,sum(m.result_ir)) END) AS field1
From tbloutputmoderesults m
Where m.sampleid = ' + cast(@sampleId as varchar(50)) + ' Group By m.FailFlag_IR,m.exposurenumber,m.lineindex) as t
Group By exposurenumber'
Select @query1a = @sql5a
Select @query1b = @sql5b
Select @query1c = @sql5c
Select @query1d = @sql5d + char(10) + 'Union All' + char(10)
Select @query5a = char(10) + 'Union All' + char(10) + @sql1
Select @query5b = @sql2
Select @query5b2 = @sql2b
Select @query5b3 = @sql2c
Select @query5b4 = @sql2d
Select @query5c = @sql3
exec(@sql6) -- create the ##tmp_results_table
Insert ##tmp_results_table exec(@query1a + @query1b + @query1c + @query1d + @query2 + @query2b1 + @query2b2 + @query2b3 + @query2b4 + @query2b5 + @query3 + @query3b1 + @query3b2 + @query3b3 + @query3b4 + @query3b5 + @query4 + @query4b1 + @query4b2 + @query4b3 + @query4b4 + @query4b5 + @query5a + @query5b + @query5b2 + @query5b3 + @query5b4 + @query5c)
declare @sqlpages varchar(8000)
exec pr_GeneratePages @sqlpages out,@maxcol,@max_nbr_cols
select @samplesql = @sqlpages
-- Drop temporary tables
if exists(select * from tempdb.information_schema.tables where table_name = '##tmp_pivot_table')
drop table ##tmp_pivot_table
END
Thank you in advanced for your time
willpash
I have inherited a stored procedure that forms the datasource for a linked subreport in MS Reporting Services 2005.
I have spent the best part of the weekend optimising this to improve the execution speed. It currently is taking 195ms to execute the query of the subreport, with the subreport taking 555ms to compile, with 2 values for the sample id, and a maximum of 10 rows being returned.
Any advice and/or observations would be greatly appreciated.
USE [HPLCData]
GO
/****** Object: StoredProcedure [dbo].[pr_HPLCRawData] Script Date: 08/30/2009 21:03:02 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[pr_HPLCRawData]
@maxcol int = 5,
@sampleId int,
@samplesql varchar(8000) output
AS
BEGIN
-- Create a temporary table populated by results for a given sampleId, and given a max number of columns
-- construct an output @samplesql string to query this table of the form:
-- Select SampleId, Summary, Col1, Col2, Col3, Col4, Col5 from ##tmp_results_table union all Select SampleId, Summary, Col6, Col7, Col8, Col9, Col10 from ##tmp_results_table union all Select ... etc ... from ##tmp_results_table union all Select SampleId, Summary, Col51, Col52,' ' as Col52,' ' as Col52,' ' as Col52 from ##tmp_results_table
--
Declare @sql1 varchar(8000)
Declare @sql2 varchar(8000)
Declare @sql2b varchar(8000)
Declare @sql2c varchar(8000)
Declare @sql2d varchar(8000)
Declare @sql3 varchar(8000)
Declare @sql4 varchar(8000)
Declare @sql5a varchar(8000)
Declare @sql5b varchar(8000)
Declare @sql5c varchar(8000)
Declare @sql5d varchar(8000)
Declare @sql6 varchar(8000)
Declare @query1a varchar(8000)
Declare @query1b varchar(8000)
Declare @query1c varchar(8000)
Declare @query1d varchar(8000)
Declare @query2 varchar(8000)
Declare @query2b1 varchar(8000)
Declare @query2b2 varchar(8000)
Declare @query2b3 varchar(8000)
Declare @query2b4 varchar(8000)
Declare @query2b5 varchar(8000)
Declare @query3 varchar(8000)
Declare @query3b1 varchar(8000)
Declare @query3b2 varchar(8000)
Declare @query3b3 varchar(8000)
Declare @query3b4 varchar(8000)
Declare @query3b5 varchar(8000)
Declare @query4 varchar(8000)
Declare @query4b1 varchar(8000)
Declare @query4b2 varchar(8000)
Declare @query4b3 varchar(8000)
Declare @query4b4 varchar(8000)
Declare @query4b5 varchar(8000)
Declare @query5a varchar(8000)
Declare @query5b varchar(8000)
Declare @query5b2 varchar(8000)
Declare @query5b3 varchar(8000)
Declare @query5b4 varchar(8000)
Declare @query5c varchar(8000)
Declare @sqlline varchar(8000)
Declare @lines int
Declare @line int
DECLARE @max_nbr_cols int
DECLARE @counter int
--Drop temporary tables
if exists(select * from tempdb.information_schema.tables where table_name = '##tmp_pivot_table')
drop table ##tmp_pivot_table
if exists(select * from tempdb.information_schema.tables where table_name = '##tmp_results_table')
drop table ##tmp_results_table
--Retrieve the total number of elements in a sample
SELECT @max_nbr_cols = COUNT(*) FROM elementlines l WHERE l.sampleid = @sampleId
-- if there is no data for this section, return an empty string
IF NOT @max_nbr_cols > 0
BEGIN
set @samplesql = ''
return
END
--Dynamically build queries to create ##tmp_pivot_table and ##tmp_results_table
SET @sqlline = 'Col1 varchar(20) NULL'
SET @counter = 2
WHILE @counter <= @max_nbr_cols
BEGIN
SET @sqlline = @sqlline + ',Col' + CONVERT(varchar, @counter) + ' varchar(20) NULL'
SET @counter = @counter + 1
END
SET @sql5a = 'CREATE TABLE ##tmp_pivot_table ( ' + @sqlline + ')'
SET @sql6 = 'CREATE TABLE ##tmp_results_table (SampleId int NULL, Summary varchar(50) NULL, ' + @sqlline + ')'
EXEC(@sql5a) -- creates the ##tmp_pivot_table
--Retrieve the total number of elements in a sample
SET @lines = @max_nbr_cols
SET @sql5a = 'INSERT INTO ##tmp_pivot_table SELECT MAX(CASE lineindex WHEN 1 THEN field1 ELSE '''' END) AS Col1'
SET @sql5b = ''
SET @sql5c = ''
SET @sql5d = ''
SET @sqlline = ''
SET @counter = 2
WHILE @counter <= @max_nbr_cols
BEGIN
SET @sqlline = ',MAX(CASE lineindex WHEN ' + CONVERT(varchar, @counter) + ' THEN field1 ELSE '''' END) AS Col' + CONVERT(varchar, @counter)
if(len(@sql5a) < 7600)
SET @sql5a = @sql5a + @sqlline
else if(len(@sql5b) < 7600)
SET @sql5b = @sql5b + @sqlline
else if(len(@sql5c) < 7600)
SET @sql5c = @sql5c + @sqlline
else if(len(@sql5d) < 7600)
SET @sql5d = @sql5d + @sqlline
SET @counter = @counter +1
END
SET @sql5d = @sql5d + ' FROM (Select l.lineIndex,l.elementname as field1 From elementlines l
Where l.sampleid = ' + cast(@sampleId as varchar(50)) + ') as t'
SET @sql5d = @sql5d + ' SELECT ' + cast(@sampleId as varchar(50)) + ' as SampleId, ''Element/Wavelength'' as Summary,* FROM ##tmp_pivot_table '
-- Retrieve average of repeats
Select @sql1 = 'Select ' + cast(@sampleId as varchar(50)) + ' as SampleId, ''Avg. of Repeats:'' as ''Summary''' + char(10)
Select @sql2 = ',MAX(CASE lineindex WHEN 1 THEN field1 ELSE '''' END) AS Col1' + char(10)
Select @sql2b = ''
Select @sql2c = ''
Select @sql2d = ''
select @sqlline = ''
Select @line = 2
while(@line <= @lines)
begin
SET @sqlline = ',MAX(CASE lineindex WHEN ' + CONVERT(varchar, @line) + ' THEN field1 ELSE '''' END) AS Col' + CONVERT(varchar, @line) + char(10)
if(len(@sql2) < 7600)
select @sql2 = @sql2 + @sqlline
else if(len(@sql2b) < 7600)
select @sql2b = @sql2b + @sqlline
else if(len(@sql2c) < 7600)
select @sql2c = @sql2c + @sqlline
else if(len(@sql2d) < 7600)
select @sql2d = @sql2d + @sqlline
select @line = @line + 1
end
Select @sql3 = 'From (Select s.lineIndex,
RTRIM(s.FailFlags_IR) COLLATE database_default+char(32)+(CASE WHEN RTRIM(s.FailFlags_IR) COLLATE database_default IN (''*'', ''^'', ''?'',''Z'', ''P'', ''D'',''N'') THEN ''*****'' ELSE CONVERT(varchar,s.averageresult_ir) END) AS field1
From tbloutputmoderesultstats s
Where s.sampleid = ' + cast(@sampleId as varchar(50)) + ') as t'
Select @query2 = @sql1
Select @query2b1 = @sql2
Select @query2b2 = @sql2b
Select @query2b3 = @sql2c
Select @query2b4 = @sql2d
Select @query2b5 = @sql3
--Retrieve Standard deviation
Select @sql1 = 'Select ' + cast(@sampleId as varchar(50)) + ' as SampleId, ''Std Dev:'' as ''Summary''' + char(10)
Select @sql3 = 'From (Select s.lineIndex,
(CASE WHEN RTRIM(s.FailFlags_IR) COLLATE database_default IN (''*'', ''^'', ''?'',''Z'', ''P'', ''D'',''N'') THEN ''----'' ELSE CONVERT(varchar,s.standarddeviation_ir) END) AS field1
From tbloutputmoderesultstats s
Where s.sampleid = ' + cast(@sampleId as varchar(50)) + ') as t'
Select @query3 = char(10) + 'Union All' + char(10) + @sql1
Select @query3b1 = @sql2
Select @query3b2 = @sql2b
Select @query3b3 = @sql2c
Select @query3b4 = @sql2d
Select @query3b5 = @sql3
--Retrieve percentage RSD
Select @sql1 = 'Select ' + cast(@sampleId as varchar(50)) + ' as SampleId, ''%RSD:'' as ''Summary''' + char(10)
Select @sql3 = 'From (Select s.lineIndex,
(CASE WHEN RTRIM(s.FailFlags_IR) COLLATE database_default IN (''*'', ''^'', ''?'',''Z'', ''P'', ''D'',''N'') THEN ''----'' ELSE CONVERT(varchar,s.percentrsd_ir) END) AS field1
From tbloutputmoderesultstats s
Where s.sampleid = ' + cast(@sampleId as varchar(50)) + ') as t'
Select @query4 = char(10) + 'Union All' + char(10) + @sql1
Select @query4b1 = @sql2
Select @query4b2 = @sql2b
Select @query4b3 = @sql2c
Select @query4b4 = @sql2d
Select @query4b5 = @sql3
--Retrieve repeat information
Select @sql1 = 'Select ' + cast(@sampleId as varchar(50)) + 'AS SampleId, ''Repeat:'' + cast(exposurenumber as varchar(10)) as ''Summary''' + char(10)
Select @sql3 = 'From (Select m.lineindex,m.exposurenumber,
(CASE WHEN RTRIM(m.FailFlag_IR) COLLATE database_default IN (''*'', ''^'', ''?'',''Z'', ''P'', ''D'',''N'') THEN RTRIM(m.FailFlag_IR) COLLATE database_default+char(32)+''----'' ELSE CONVERT(varchar,sum(m.result_ir)) END) AS field1
From tbloutputmoderesults m
Where m.sampleid = ' + cast(@sampleId as varchar(50)) + ' Group By m.FailFlag_IR,m.exposurenumber,m.lineindex) as t
Group By exposurenumber'
Select @query1a = @sql5a
Select @query1b = @sql5b
Select @query1c = @sql5c
Select @query1d = @sql5d + char(10) + 'Union All' + char(10)
Select @query5a = char(10) + 'Union All' + char(10) + @sql1
Select @query5b = @sql2
Select @query5b2 = @sql2b
Select @query5b3 = @sql2c
Select @query5b4 = @sql2d
Select @query5c = @sql3
exec(@sql6) -- create the ##tmp_results_table
Insert ##tmp_results_table exec(@query1a + @query1b + @query1c + @query1d + @query2 + @query2b1 + @query2b2 + @query2b3 + @query2b4 + @query2b5 + @query3 + @query3b1 + @query3b2 + @query3b3 + @query3b4 + @query3b5 + @query4 + @query4b1 + @query4b2 + @query4b3 + @query4b4 + @query4b5 + @query5a + @query5b + @query5b2 + @query5b3 + @query5b4 + @query5c)
declare @sqlpages varchar(8000)
exec pr_GeneratePages @sqlpages out,@maxcol,@max_nbr_cols
select @samplesql = @sqlpages
-- Drop temporary tables
if exists(select * from tempdb.information_schema.tables where table_name = '##tmp_pivot_table')
drop table ##tmp_pivot_table
END
Thank you in advanced for your time
willpash