Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 Query plan based on number of rows?

Author  Topic 

samuelclay
Yak Posting Veteran

71 Posts

Posted - 2006-12-14 : 15:26:27
I have an update query that works fine on my dev box (sql2005) but when I run it on the production machine (sql2000) it chokes, giving this error:
quote:
Server: Msg 8623, Level 16, State 1, Line 1
Internal Query Processor Error: The query processor could not produce a query plan. Contact your primary support provider for more information.

At first I thought it was some system setting, but they look the same. So I started testing with some fake data and suddenly it worked. But running against actual data still choked. The only difference I saw between the test and actual data was the number of records, so I kept adding rows to my sample data and found it quit working at 592 rows. At 591 the query works fine, but anything above that and I get the error above.

So my questions:
1) Is the ability to generate a query plan really based on the number of rows?
2) Have others seen this problem?
3) Ways around it?
I know I have run update queries on bigger sets of data than 592 rows, is there something about corelated subquiries that are affected by the number of rows?

Here is the code, does anyone else get the same results

-- udf called in update query
CREATE FUNCTION [dbo].[rfn_GetFiscalYear]
( @FYB int,@Date datetime )
RETURNS int AS
BEGIN
-- Purpose : Get Fiscal year from input date
DECLARE @FY int, @AddAmt int
SELECT @AddAmt = 0
IF ((@FYB > 1) and (datepart(mm,@Date) >= @FYB))
SELECT @AddAmt = 1
SELECT @FY = datepart(yyyy,@Date) + @AddAmt
RETURN @FY
END

-- create temp table
CREATE TABLE #DrawingData
( pnID int,
Part_Number varchar(50),
Part_Nomenclature varchar(512),
Vendor_PN varchar(50),
Next_Assy varchar(50),
Reason_Initiated varchar(512),
External_Case_Num varchar(50),
Log_in_Date datetime,
Case_Status varchar(50),
Recommended_Resolution varchar(30),
Log_Out_Date datetime,
Case_Number int,
FiscalYear char(4),
Case_Num_Cmplte varchar(50)
)
GO

INSERT INTO #DrawingData
( pnID, Part_Number, Part_Nomenclature, Vendor_PN, Next_Assy, Reason_Initiated,
External_Case_Num, Log_in_Date, Case_Status, Recommended_Resolution, Log_Out_Date
)
SELECT 1,'lskjdf','lakdjfsd','ladkjfd','ljdlfkjad','lfjalskdfj','test1', getdate(),'lsjkdflkdj','lakdjfdj',getdate() union all
SELECT 1,'lskjdf','lakdjfsd','ladkjfd','ljdlfkjad','lfjalskdfj','test2', getdate(),'lsjkdflkdj','lakdjfdj',getdate() union all
SELECT 1,'lskjdf','lakdjfsd','ladkjfd','ljdlfkjad','lfjalskdfj','test3', getdate(),'lsjkdflkdj','lakdjfdj',getdate() union all
SELECT 1,'lskjdf','lakdjfsd','ladkjfd','ljdlfkjad','lfjalskdfj','test4', getdate(),'lsjkdflkdj','lakdjfdj',getdate() union all
SELECT 1,'lskjdf','lakdjfsd','ladkjfd','ljdlfkjad','lfjalskdfj','test5', getdate(),'lsjkdflkdj','lakdjfdj',getdate() union all
SELECT 1,'lskjdf','lakdjfsd','ladkjfd','ljdlfkjad','lfjalskdfj','test6', getdate(),'lsjkdflkdj','lakdjfdj',getdate() union all
SELECT 1,'lskjdf','lakdjfsd','ladkjfd','ljdlfkjad','lfjalskdfj','test7', getdate(),'lsjkdflkdj','lakdjfdj',getdate() union all
SELECT 1,'lskjdf','lakdjfsd','ladkjfd','ljdlfkjad','lfjalskdfj','test8', getdate(),'lsjkdflkdj','lakdjfdj',getdate() union all
SELECT 1,'lskjdf','lakdjfsd','ladkjfd','ljdlfkjad','lfjalskdfj','test9', getdate(),'lsjkdflkdj','lakdjfdj',getdate() union all
SELECT 1,'lskjdf','lakdjfsd','ladkjfd','ljdlfkjad','lfjalskdfj','test10', getdate(),'lsjkdflkdj','lakdjfdj',getdate()
-- This can be run multiple times or added to for larger recordsets

-- update table to add case number and fiscal year info
UPDATE c
SET Case_Number = ( SELECT isnull(COUNT(d.Log_In_Date),0)+1
FROM #DrawingData d
WHERE
( dbo.rfn_GetFiscalYear(10, d.Log_in_Date) = dbo.rfn_GetFiscalYear(10, c.Log_in_Date)
AND ( d.Log_In_Date < c.Log_In_Date
OR ( d.Log_In_Date = c.Log_In_Date
AND left(d.External_Case_Num,10) < left(c.External_Case_Num,10)
)
)
)
),
FiscalYear = dbo.rfn_GetFiscalYear(10, c.Log_in_Date)
FROM #DrawingData c
GO

snSQL
Master Smack Fu Yak Hacker

1837 Posts

Posted - 2006-12-14 : 15:52:33
Have you seen this
http://support.microsoft.com/kb/841404

I tried your test on SQL Server 2000 with SP4 installed and it worked fine on 800 records (takes 17 seconds), and 1800 records (takes 58 seconds)
Go to Top of Page

samuelclay
Yak Posting Veteran

71 Posts

Posted - 2006-12-14 : 17:05:33
I have read that article. From reading that, though, it didn't seem to be record size dependent, but dealt with the complexity of the relationship of the inner query. My surprise was on the fact it works for samll sets of data but not larger ones...

The server is supposed to be up to date with all sp's and hot fixes. I will check further on that.

thanks for the response.

Go to Top of Page

snSQL
Master Smack Fu Yak Hacker

1837 Posts

Posted - 2006-12-14 : 17:34:03
BTW - here's a more efficient implementation of your function. This changed the time for the update from 58 seconds to 49 seconds for 1800 records on my machine.

CREATE FUNCTION [dbo].[rfn_GetFiscalYear] 
( @FYB int,@Date datetime )
RETURNS int AS
BEGIN
-- Purpose : Get Fiscal year from input date
RETURN year(@Date) + CASE WHEN month(@Date) >= @FYB AND (@FYB > 1) THEN 1 ELSE 0 END
END
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2006-12-15 : 03:14:01
I would do the update in two passes.

SET FiscalYear = dbo.rfn_GetFiscalYear(10, c.Log_in_Date)

in the first pass, then do the Update with the CASE statement; the FiscalYear will already be available in the #DrawingData table

Perhaps put an Index on #DrawingData for FiscalYear, Log_in_Date, External_Case_Num to cover the sub query too.

Kristen
Go to Top of Page
   

- Advertisement -