|
database
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Help with Stored Procedure, Taking too long to run...I have a stored procedure that i've been using for the past 2 years... it has started to slow down on some of the complex searches... But i'll provide the tables and a clean version of the stored procedure for anyone who can help... (clean showing procedure without commented stuff out).. I'm running SQL Server 2000 at this time... i plan on upgrading to SQL Server 2005 in the very near future... To sum up, this stored procedure will read data from two identical tables, one with 100k records, and the other with 600k records. The records are sorted into a temp table, and then the records for page XX are extracted based on how many records per page is requested. All paging happens server side, this way only the data required is returned. I also have 3 other tables that are used with these tables, but they aren't used as much... I do have fulltext set up on Items and PubItems tables... When a search is done by ISBN on both, the time taken is between 100 and 500 MS... When i do a search (say by title or author), the time taken is between 1000 MS and ... well, i've seen numbers up around 200000 MS or higher... I'm not going to provide any data inserts as trying to run this against a table with 5-100 records isn't going to show how slow my searches can be... Example procedure runs: 1: exec sp_PagedItems4 'Both','I.ISBN=''9781111111113''','TitleIndex',1,15 1: This search was under 1 second, and returned the one record as expected. 2: exec sp_PagedItems4 'Both','I.TitleText Like ''%Garfield%''','TitleIndex',1,15 2: This search took 5 seconds, and returned the 15 records for page 1, but overall count is 265. 3: exec sp_PagedItems4 'Both', '(FREETEXT (I.TitleText, ''"books"'') OR FREETEXT (I.Subtitle, ''"books"'') OR FREETEXT (I.AuthorText, ''"books"'') OR FREETEXT (I.IllusText, ''"books"'')) AND (FREETEXT (I.TitleText, ''"about"'') OR FREETEXT (I.Subtitle, ''"about"'') OR FREETEXT (I.AuthorText, ''"about"'') OR FREETEXT (I.IllusText, ''"about"'')) AND (FREETEXT (I.TitleText, ''"crafts"'') OR FREETEXT (I.Subtitle, ''"crafts"'') OR FREETEXT (I.AuthorText, ''"crafts"'') OR FREETEXT (I.IllusText, ''"crafts"''))' ,'TitleIndex',1,15 3: This search took 1 minute and 45 seconds (when run from SQL Query Analyzer), and returned ONE record from PubItems. Any help is very much appreciated... Thanks! ---------------------------------------------------------------------------- ---------------------------- CREATE TABLE [dbo].[AwardType] ( [AwardCode] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , [AwardDesc] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ) ON [PRIMARY] GO CREATE TABLE [dbo].[Awards] ( [ItemID] [int] NOT NULL , [AwardCode] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ) ON [PRIMARY] GO CREATE TABLE [dbo].[ReviewType] ( [ReviewCode] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , [ReviewDesc] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ) ON [PRIMARY] GO CREATE TABLE [dbo].[Reviews] ( [ItemID] [int] NOT NULL , [ReviewCode] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ) ON [PRIMARY] GO CREATE TABLE Items ( ID int IDENTITY(1,1) PRIMARY KEY, ItemID int null, PubSource nvarchar(255) default (''), ISBN nvarchar(13) null, Dewey nvarchar(20) null, TitleIndex nvarchar(175) null, AuthorIndex nvarchar(50) null, PubYear nvarchar(30) null, PubDate datetime null, SeriesName nvarchar(150) null, SeriesNumber int null ) GO CREATE TABLE PubItems ( ID int IDENTITY(1,1) PRIMARY KEY, ItemID int null, PubSource nvarchar(255) default (''), ISBN nvarchar(13) null, Dewey nvarchar(20) null, TitleIndex nvarchar(175) null, AuthorIndex nvarchar(50) null, PubYear nvarchar(30) null, PubDate datetime null, SeriesName nvarchar(150) null, SeriesNumber int null ) GO /* sp_PagedItems4 - This procedure is the continuation of the original sp_PagedItems, which would allow us to grab records from BOTH Items and PubItems, and eliminate the Items in the PubItems Table which are in Items. The only difference here is that we only return the minimal data fields (which should hopefully speed up the query). */ CREATE PROCEDURE sp_PagedItems4 ( @TableExt nvarchar(10), @Where nvarchar(1500), @SortColumn nvarchar(300), @Page int, @RecsPerPage int ) WITH RECOMPILE AS DECLARE @Where2 nvarchar(1500) DECLARE @Table nvarchar(200) DECLARE @Table2 nvarchar(200) DECLARE @Fields nvarchar(2000) DECLARE @Fields2 nvarchar(2000) DECLARE @FieldsInsert nvarchar(2000) DECLARE @FieldsI nvarchar(2000) DECLARE @query nvarchar(4000) DECLARE @TotalRec int DECLARE @AwardReview char(1) Set @AwardReview = 'N' Set @Where2 = @Where Set @Where2 = REPLACE(@Where2,'I.','PI.') --Fields, Blurb, SecBlurb, SetID, BestBlurb are ntext fields. These fields need to be removed from the union, but put in after --the data is done. Set @Fields = 'I.ItemID, '''', I.ISBN, I.Dewey, I.TitleIndex, I.AuthorIndex, I.PubYear, I.PubDate, I.SeriesName, I.SeriesNumber' Set @Fields2 = 'PI.ItemID, PI.PubSource, PI.ISBN, PI.Dewey, PI.TitleIndex, PI.AuthorIndex, PI.PubYear, PI.PubDate, PI.SeriesName, PI.SeriesNumber' Set @Table = 'Items I' Set @Table2 = 'PubItems PI' Set @FieldsI = 'I.ItemID, I.PubSource, I.ISBN, I.Dewey, I.TitleIndex, I.AuthorIndex, I.PubYear, I.PubDate, I.SeriesName, I.SeriesNumber' --Check for "A", "R" or "AD" in the Where as we need to join the tables if that's the case. (Items only) if charindex('A.', @Where) > 0 begin Set @Table = @Table + ' JOIN Awards A ON I.ItemID = A.ItemID ' Set @AwardReview = 'Y' end if charindex('R.', @Where) > 0 begin Set @Table = @Table + ' JOIN Reviews R ON I.ItemID = R.ItemID ' Set @AwardReview = 'Y' end -- Do not return # rows inserted in temp table. SET NOCOUNT ON --Create Temp Table CREATE TABLE #TempItems ( ID int IDENTITY(1,1) PRIMARY KEY, ItemID int null, PubSource nvarchar(255) default (''), ISBN nvarchar(13) null, Dewey nvarchar(20) null, TitleIndex nvarchar(175) null, AuthorIndex nvarchar(50) null, PubYear nvarchar(30) null, PubDate datetime null, SeriesName nvarchar(150) null, SeriesNumber int null ) -- Insert the rows from Items into the temp table. if @AwardReview = 'N' begin --No Award/Review, let's union this... if @tableext = 'Both' Or @TableExt = 'Items' begin SELECT @query = 'INSERT INTO #TempItems ' + ' (' + @FieldsI + ') ' + ' SELECT ' + @Fields + ' FROM ' + @Table + ' WHERE ' + @Where end if @tableext = 'Both' begin Select @query = @query + ' UNION ' + ' SELECT ' + @Fields2 + ' FROM ' + @Table2 + ' WHERE ' + @Where2 end if @TableExt = 'PubItems' begin SELECT @query = 'INSERT INTO #TempItems ' + ' (' + @Fields2 + ') ' + ' SELECT ' + @Fields2 + ' FROM ' + @Table2 + ' WHERE ' + @Where2 end if @SortColumn <> '' And Not isnull(@SortColumn,'') = '' SELECT @query = @query + ' ORDER BY ' + @SortColumn --Print @Query exec sp_executesql @query end else begin --There is an award/review requested, so don't even look at pubitems if @tableext = 'Both' Or @TableExt = 'Items' begin SELECT @query = 'INSERT INTO #TempItems ' + ' (' + @FieldsI + ') ' + ' SELECT ' + @Fields + ' FROM ' + @Table + ' WHERE ' + @Where if @SortColumn <> '' And Not isnull(@SortColumn,'') = '' SELECT @query = @query + ' ORDER BY ' + @SortColumn --print @query exec sp_executesql @query end end SET @TotalRec = (SELECT COUNT(ID) FROM #TempItems) --Check if there are any records. If there are, return everything, else return all zeros and --no resultset. if @TotalRec > 0 begin DECLARE @MoreRecords int DECLARE @FirstRec int DECLARE @LastRec int DECLARE @DispFirstRec int DECLARE @DispLastRec int /*Find out first and last record we want If Page=0, then we want all records! */ if @Page = 0 begin SELECT @FirstRec = 0 SELECT @LastRec = @TotalRec + 1 end else begin SELECT @FirstRec = (@Page - 1) * @RecsPerPage SELECT @LastRec = (@Page * @RecsPerPage + 1) end -- Now return the set of paged records, plus an indication if we -- have more to return or not. SET @MoreRecords = (SELECT COUNT(ID) FROM #TempItems TI WHERE TI.ID >= @LastRec) -- Check @FirstRec & @LastRec. -- @FirstRec should always be +1 based on the record count. Set @DispFirstRec = @FirstRec + 1 -- @LastRec should be +1 unless it is on the last page. if @LastRec > @TotalRec Set @DispLastRec = @TotalRec else Set @DispLastRec = @LastRec - 1 --First ResultSet (TotalRec, MoreRecords, FirstRec, LastRec SELECT TotalRec = @TotalRec, MoreRecords = @MoreRecords, FirstRec = @DispFirstRec, LastRec = @DispLastRec --Second ResultSet (All Records) SELECT ID, ItemID, PubSource, ISBN FROM #TempItems WHERE ID>@FirstRec AND ID<@LastRec --exec sp_executesql @query end else begin --Empty ResultSet (Return all Zeros) SELECT TotalRec = 0, MoreRecords = 0, FirstRec = 0, LastRec =0 SELECT @query end --Don't need the Drop table as its automatically done after this procedure is done. --DROP TABLE #TempItems -- Turn NOCOUNT back OFF SET NOCOUNT OFF GO Hi,
Is there anyone able to help me out with this? Show quote "RL Tech" <tech_support@nospamuls.com> wrote in message --news:%23PKjbQ6QGHA.1096@TK2MSFTNGP11.phx.gbl... > Hello, > > I have a stored procedure that i've been using for the past 2 years... it > has started to slow down on some of the complex searches... But i'll provide > the tables and a clean version of the stored procedure for anyone who can > help... (clean showing procedure without commented stuff out).. > > I'm running SQL Server 2000 at this time... i plan on upgrading to SQL > Server 2005 in the very near future... > > To sum up, this stored procedure will read data from two identical tables, > one with 100k records, and the other with 600k records. The records are > sorted into a temp table, and then the records for page XX are extracted > based on how many records per page is requested. All paging happens server > side, this way only the data required is returned. > > I also have 3 other tables that are used with these tables, but they aren't > used as much... > > I do have fulltext set up on Items and PubItems tables... > > When a search is done by ISBN on both, the time taken is between 100 and 500 > MS... > When i do a search (say by title or author), the time taken is between 1000 > MS and ... well, i've seen numbers up around 200000 MS or higher... > > I'm not going to provide any data inserts as trying to run this against a > table with 5-100 records isn't going to show how slow my searches can be... > Example procedure runs: > 1: exec sp_PagedItems4 'Both','I.ISBN=''9781111111113''','TitleIndex',1,15 > 1: This search was under 1 second, and returned the one record as expected. > 2: exec sp_PagedItems4 'Both','I.TitleText Like > ''%Garfield%''','TitleIndex',1,15 > 2: This search took 5 seconds, and returned the 15 records for page 1, but > overall count is 265. > 3: exec sp_PagedItems4 'Both', > '(FREETEXT (I.TitleText, ''"books"'') OR FREETEXT (I.Subtitle, ''"books"'') > OR FREETEXT (I.AuthorText, ''"books"'') OR FREETEXT (I.IllusText, > ''"books"'')) AND (FREETEXT (I.TitleText, ''"about"'') OR FREETEXT > (I.Subtitle, ''"about"'') OR FREETEXT (I.AuthorText, ''"about"'') OR > FREETEXT (I.IllusText, ''"about"'')) AND (FREETEXT (I.TitleText, > ''"crafts"'') OR FREETEXT (I.Subtitle, ''"crafts"'') OR FREETEXT > (I.AuthorText, ''"crafts"'') OR FREETEXT (I.IllusText, ''"crafts"''))' > ,'TitleIndex',1,15 > 3: This search took 1 minute and 45 seconds (when run from SQL Query > Analyzer), and returned ONE record from PubItems. > > Any help is very much appreciated... > Thanks! > > -------------------------------------------------------------------------- > ---------------------------- > CREATE TABLE [dbo].[AwardType] ( > [AwardCode] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > [AwardDesc] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL > ) ON [PRIMARY] > GO > > CREATE TABLE [dbo].[Awards] ( > [ItemID] [int] NOT NULL , > [AwardCode] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL > ) ON [PRIMARY] > GO > > CREATE TABLE [dbo].[ReviewType] ( > [ReviewCode] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL > , > [ReviewDesc] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL > ) ON [PRIMARY] > GO > > CREATE TABLE [dbo].[Reviews] ( > [ItemID] [int] NOT NULL , > [ReviewCode] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL > ) ON [PRIMARY] > GO > > CREATE TABLE Items > ( > ID int IDENTITY(1,1) PRIMARY KEY, > ItemID int null, > PubSource nvarchar(255) default (''), > ISBN nvarchar(13) null, > Dewey nvarchar(20) null, > TitleIndex nvarchar(175) null, > AuthorIndex nvarchar(50) null, > PubYear nvarchar(30) null, > PubDate datetime null, > SeriesName nvarchar(150) null, > SeriesNumber int null > ) > GO > > CREATE TABLE PubItems > ( > ID int IDENTITY(1,1) PRIMARY KEY, > ItemID int null, > PubSource nvarchar(255) default (''), > ISBN nvarchar(13) null, > Dewey nvarchar(20) null, > TitleIndex nvarchar(175) null, > AuthorIndex nvarchar(50) null, > PubYear nvarchar(30) null, > PubDate datetime null, > SeriesName nvarchar(150) null, > SeriesNumber int null > ) > GO > > /* > sp_PagedItems4 - > > This procedure is the continuation of the original sp_PagedItems, which > would allow us to grab records from BOTH Items and PubItems, and > eliminate the Items in the PubItems Table which are in Items. The only > difference here is that we only return the minimal data fields (which > should > hopefully speed up the query). > */ > > CREATE PROCEDURE sp_PagedItems4 > ( > @TableExt nvarchar(10), > @Where nvarchar(1500), > @SortColumn nvarchar(300), > @Page int, > @RecsPerPage int > ) > WITH RECOMPILE > AS > DECLARE @Where2 nvarchar(1500) > DECLARE @Table nvarchar(200) > DECLARE @Table2 nvarchar(200) > DECLARE @Fields nvarchar(2000) > DECLARE @Fields2 nvarchar(2000) > DECLARE @FieldsInsert nvarchar(2000) > DECLARE @FieldsI nvarchar(2000) > > DECLARE @query nvarchar(4000) > DECLARE @TotalRec int > > DECLARE @AwardReview char(1) > > Set @AwardReview = 'N' > Set @Where2 = @Where > Set @Where2 = REPLACE(@Where2,'I.','PI.') > > --Fields, Blurb, SecBlurb, SetID, BestBlurb are ntext fields. These fields > need to be removed from the union, but put in after > --the data is done. > Set @Fields = 'I.ItemID, '''', I.ISBN, I.Dewey, I.TitleIndex, I.AuthorIndex, > I.PubYear, I.PubDate, I.SeriesName, I.SeriesNumber' > Set @Fields2 = 'PI.ItemID, PI.PubSource, PI.ISBN, PI.Dewey, PI.TitleIndex, > PI.AuthorIndex, PI.PubYear, PI.PubDate, PI.SeriesName, PI.SeriesNumber' > > Set @Table = 'Items I' > Set @Table2 = 'PubItems PI' > > Set @FieldsI = 'I.ItemID, I.PubSource, I.ISBN, I.Dewey, I.TitleIndex, > I.AuthorIndex, I.PubYear, I.PubDate, I.SeriesName, I.SeriesNumber' > > --Check for "A", "R" or "AD" in the Where as we need to join the tables if > that's the case. (Items only) > if charindex('A.', @Where) > 0 > begin > Set @Table = @Table + ' JOIN Awards A ON I.ItemID = A.ItemID ' > Set @AwardReview = 'Y' > end > > if charindex('R.', @Where) > 0 > begin > Set @Table = @Table + ' JOIN Reviews R ON I.ItemID = R.ItemID ' > Set @AwardReview = 'Y' > end > > -- Do not return # rows inserted in temp table. > SET NOCOUNT ON > > --Create Temp Table > CREATE TABLE #TempItems > ( > ID int IDENTITY(1,1) PRIMARY KEY, > ItemID int null, > PubSource nvarchar(255) default (''), > ISBN nvarchar(13) null, > Dewey nvarchar(20) null, > TitleIndex nvarchar(175) null, > AuthorIndex nvarchar(50) null, > PubYear nvarchar(30) null, > PubDate datetime null, > SeriesName nvarchar(150) null, > SeriesNumber int null > ) > > -- Insert the rows from Items into the temp table. > if @AwardReview = 'N' > begin > --No Award/Review, let's union this... > if @tableext = 'Both' Or @TableExt = 'Items' > begin > SELECT @query = 'INSERT INTO #TempItems ' + > ' (' + @FieldsI + ') ' + > ' SELECT ' + @Fields + > ' FROM ' + @Table + > ' WHERE ' + @Where > end > > if @tableext = 'Both' > begin > Select @query = @query + ' UNION ' + > ' SELECT ' + @Fields2 + > ' FROM ' + @Table2 + > ' WHERE ' + @Where2 > end > > if @TableExt = 'PubItems' > begin > SELECT @query = 'INSERT INTO #TempItems ' + > ' (' + @Fields2 + ') ' + > ' SELECT ' + @Fields2 + > ' FROM ' + @Table2 + > ' WHERE ' + @Where2 > end > > if @SortColumn <> '' And Not isnull(@SortColumn,'') = '' > SELECT @query = @query + ' ORDER BY ' + @SortColumn > > --Print @Query > exec sp_executesql @query > end > else > begin > --There is an award/review requested, so don't even look at pubitems > if @tableext = 'Both' Or @TableExt = 'Items' > begin > SELECT @query = 'INSERT INTO #TempItems ' + > ' (' + @FieldsI + ') ' + > ' SELECT ' + @Fields + > ' FROM ' + @Table + > ' WHERE ' + @Where > > if @SortColumn <> '' And Not isnull(@SortColumn,'') = '' > SELECT @query = @query + ' ORDER BY ' + @SortColumn > --print @query > exec sp_executesql @query > end > end > > SET @TotalRec = > (SELECT COUNT(ID) > FROM #TempItems) > > --Check if there are any records. If there are, return everything, else > return all zeros and > --no resultset. > if @TotalRec > 0 > begin > DECLARE @MoreRecords int > DECLARE @FirstRec int > DECLARE @LastRec int > DECLARE @DispFirstRec int > DECLARE @DispLastRec int > > /*Find out first and last record we want > If Page=0, then we want all records! > */ > > if @Page = 0 > begin > > SELECT @FirstRec = 0 > SELECT @LastRec = @TotalRec + 1 > end > else > begin > SELECT @FirstRec = (@Page - 1) * @RecsPerPage > SELECT @LastRec = (@Page * @RecsPerPage + 1) > end > > -- Now return the set of paged records, plus an indication if we > -- have more to return or not. > SET @MoreRecords = > (SELECT COUNT(ID) > FROM #TempItems TI > WHERE TI.ID >= @LastRec) > > -- Check @FirstRec & @LastRec. > -- @FirstRec should always be +1 based on the record count. > Set @DispFirstRec = @FirstRec + 1 > > -- @LastRec should be +1 unless it is on the last page. > if @LastRec > @TotalRec > Set @DispLastRec = @TotalRec > else > Set @DispLastRec = @LastRec - 1 > > --First ResultSet (TotalRec, MoreRecords, FirstRec, LastRec > SELECT TotalRec = @TotalRec, MoreRecords = @MoreRecords, FirstRec = > @DispFirstRec, LastRec = @DispLastRec > --Second ResultSet (All Records) > SELECT ID, ItemID, PubSource, ISBN > FROM #TempItems > WHERE ID>@FirstRec AND ID<@LastRec > > --exec sp_executesql @query > end > else > begin > --Empty ResultSet (Return all Zeros) > SELECT TotalRec = 0, MoreRecords = 0, FirstRec = 0, LastRec =0 > SELECT @query > end > > --Don't need the Drop table as its automatically done after this procedure > is done. > --DROP TABLE #TempItems > > -- Turn NOCOUNT back OFF > > SET NOCOUNT OFF > GO > > After a quick look, a fews comments...
First, there are other ways to do paging, see http://www.aspfaq.com/show.asp?id=2120 If you move to SQL Server 2005, you can also use ROW_NUMBER()...OVER() You have two tables (Items and PubItems) with identical columns which you UNION together, this will eliminate duplicates based on all column which can be expensive. Why isn't this a single table? Your JOINs to Awards and Reviews could use EXISTS. You are copying all of your data into your temporary table (presumably becasue of the earlier UNION). You may find it more efficient to copy only the keys (not in your DDL) and then join the page from your temporary table back to your main tables. The SELECT that returns the data SELECT ID, ItemID, PubSource, ISBN FROM #TempItems should really have an ORDER BY ID as the order isn't guaranteed otherwise. Thank you for taking the time to look over my script...
I wrote that script based on what was available at the time and known about paging... i see by the link at aspfaq, that there has been some improvements in the ways paging works... i'll see what i can do to implement these possible changes... You did mention that in SQL Server 2005, i can use these new commands (ROW_NUMBER, OVER)... have you used these commands yourself? i'm just curious on how much better they are... We are considering moving up to sql server 2005, but really just looking at cost differences, and also the time required for me to learn the new server (as i have not had time to learn about it...) These 2 tables aren't a single table mainly because i wanted to keep the data separate (as the source of the data is different for both)... but i did want to allow users to search both tables at the same time (if they wished). I'll have to consider putting them in one table, but would rather keep it separate. You mentioned that i could use EXISTS for the JOINs to Awards/Reviews.. do you have an example on how i would use that? Thanks... I copied all the data into the temp table, (not because of the union, as i original had it doing two inserts/selects based on the table requests)... i found the union to actually be faster than using insert/select twice.. but i cut down the # of fields from the original (around 80 fields) to the current 10... This way the website will pull each record individually once the ID # is known... Fair enough with the order by id... i guess it never happened where the items weren't actually in order because i have an order by (sort by param by customer profile) which is passed in and handled that way... I thank you for your response, and look forward to any further possible fixes.. <markc***@hotmail.com> wrote in message Show quote news:1142287604.330301.206650@p10g2000cwp.googlegroups.com... > After a quick look, a fews comments... > First, there are other ways to do paging, see > http://www.aspfaq.com/show.asp?id=2120 > If you move to SQL Server 2005, you can also use ROW_NUMBER()...OVER() > > You have two tables (Items and PubItems) with identical columns which > you UNION together, this will eliminate duplicates based on > all column which can be expensive. Why isn't this a single table? > Your JOINs to Awards and Reviews could use EXISTS. > > You are copying all of your data into your > temporary table (presumably becasue of the earlier UNION). > You may find it more efficient to copy only the keys > (not in your DDL) and then join the page from your > temporary table back to your main tables. > > The SELECT that returns the data > > SELECT ID, ItemID, PubSource, ISBN > FROM #TempItems > > should really have an ORDER BY ID as the order isn't guaranteed > otherwise. > Assuming that the Items and PubItems are now the single
table (PubItems) with an extra column to determine the source ItemSource CHAR(1) NOT NULL CHECK (ItemSource IN ('I','P')) and there is a unique constraint somewhere, e.g. ISBN nvarchar(13) NOT NULL , UNIQUE (ISBN), using SQL Server 2005, you can do this, without requiring a temporary table WITH CTE_PubItems(ID, ItemID, PubSource, ISBN) AS ( SELECT ROW_NUMBER() OVER(ORDER BY P.Dewey, P.TitleIndex), P.ItemID, P.PubSource, P.ISBN FROM PubItems P WHERE ItemSource ='P' AND EXISTS(SELECT * FROM Awards A WHERE P.ItemID = A.ItemID AND A.AwardCode='???') AND EXISTS(SELECT * FROM Reviews R WHERE P.ItemID = R.ItemID AND R.ReviewCode='???') -- AND other conditions ) SELECT ID, ItemID, PubSource, ISBN FROM CTE_PubItems WHERE ID>@FirstRec AND ID<@LastRec ORDER BY ID You'll have to use dynamic SQL as your WHERE clause and ORDER BY are user-defined. Good to know.. thanks for the information...
If i ever move to 2005, then i'll have something to read up (and lots to learn) if we move to it.. Thanks again. <markc***@hotmail.com> wrote in message Show quote news:1142417136.877267.81450@j33g2000cwa.googlegroups.com... > Assuming that the Items and PubItems are now the single > table (PubItems) with an extra column to determine the source > > ItemSource CHAR(1) NOT NULL CHECK (ItemSource IN ('I','P')) > > and there is a unique constraint somewhere, e.g. > > ISBN nvarchar(13) NOT NULL , > UNIQUE (ISBN), > > using SQL Server 2005, you can do this, without requiring > a temporary table > > WITH CTE_PubItems(ID, ItemID, PubSource, ISBN) > AS > ( > SELECT ROW_NUMBER() OVER(ORDER BY P.Dewey, P.TitleIndex), > P.ItemID, P.PubSource, P.ISBN > FROM PubItems P > WHERE ItemSource ='P' > AND EXISTS(SELECT * FROM Awards A WHERE P.ItemID = A.ItemID > AND A.AwardCode='???') > AND EXISTS(SELECT * FROM Reviews R WHERE P.ItemID = R.ItemID > AND R.ReviewCode='???') > -- AND other conditions > ) > SELECT ID, ItemID, PubSource, ISBN > FROM CTE_PubItems > WHERE ID>@FirstRec AND ID<@LastRec > ORDER BY ID > > You'll have to use dynamic SQL as your > WHERE clause and ORDER BY are user-defined. > Hello again,
At this moment, we cannot move to SQL 2005.... so i need some help with this still in increasing the response time with this stored procedure.. I'm not sure if my indexes are correct, although i imagine it is correct as searches work and are somewhat quick. I'd like to leave the 2 tables as 2 tables for now... Anyone else have any other suggestions? Thanks. <markc***@hotmail.com> wrote in message Show quote news:1142287604.330301.206650@p10g2000cwp.googlegroups.com... > After a quick look, a fews comments... > First, there are other ways to do paging, see > http://www.aspfaq.com/show.asp?id=2120 > If you move to SQL Server 2005, you can also use ROW_NUMBER()...OVER() > > You have two tables (Items and PubItems) with identical columns which > you UNION together, this will eliminate duplicates based on > all column which can be expensive. Why isn't this a single table? > Your JOINs to Awards and Reviews could use EXISTS. > > You are copying all of your data into your > temporary table (presumably becasue of the earlier UNION). > You may find it more efficient to copy only the keys > (not in your DDL) and then join the page from your > temporary table back to your main tables. > > The SELECT that returns the data > > SELECT ID, ItemID, PubSource, ISBN > FROM #TempItems > > should really have an ORDER BY ID as the order isn't guaranteed > otherwise. > |
|||||||||||||||||||||||