Wrox Programmer Forums
|
SQL Server 2000 General discussion of Microsoft SQL Server -- for topics that don't fit in one of the more specific SQL Server forums. version 2000 only. There's a new forum for SQL Server 2005.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the SQL Server 2000 section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old October 30th, 2003, 11:21 AM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 1,101
Thanks: 0
Thanked 2 Times in 2 Posts
Default Optimizing Query

I have a Stored Proc that is used to generate a report. It's taking, on average, 1:40 to run. Of course, this is causing timeouts with the web site that is querying it.

Anyone have any advice on how I can improve this Query?


Code:
    SET NOCOUNT ON 
    SELECT t_CallInstance.PDIControlID, t_Target.PhysicianFirstName, t_Target.PhysicianLastName, 
t_DetailOrder.ProductID, t_TargetFrequency.Frequency, t_DetailOrder.DetailOrder
FROM         t_TargetFrequency INNER JOIN
                      t_Target ON t_TargetFrequency.PdiControlID = t_Target.PDIControlID INNER JOIN
                      t_DetailOrder ON t_TargetFrequency.ProductID = t_DetailOrder.ProductID INNER JOIN
                      t_CallInstance ON t_Target.PDIControlID = t_CallInstance.PDIControlID AND t_DetailOrder.CallInstanceID = t_CallInstance.CallInstanceID AND 
                      t_DetailOrder.CallInstanceID = t_CallInstance.CallInstanceID
WHERE     (t_CallInstance.TerritoryID = @terrid) AND (t_CallInstance.CallDate between @startdt and @enddt OR t_CallInstance.CallDate = @startdt OR t_CallInstance.CallDate = @enddt) 
UNION ALL
SELECT DISTINCT
                      t_target.PDIControlID, t_target.PhysicianFirstName, t_target.PhysicianLastName, t_TargetFrequency.ProductID, t_TargetFrequency.Frequency, 0 as DetailOrder
FROM         t_Target INNER JOIN t_CallInstance on (t_CallInstance.PDIControlID <> t_Target.PDIControlID) AND (t_CallInstance.PDIControlID <> t_Target.PDIControlID) INNER JOIN
              t_TargetFrequency ON t_target.PDIControlID = t_TargetFrequency.PdiControlID 
                      CROSS JOIN t_Location lc 
WHERE     (lc.Territory = @terrid ) AND (t_target.PDIControlID = lc.PDIControlID) AND (t_Target.PDIControlID NOT IN(SELECT PDIControlID from t_CallInstance)) 
ORDER BY t_Target.PhysicianLastName, t_CallInstance.PDIControlID ASC 
    RETURN
Hal Levy
Web Developer, PDI Inc.

NOT a Wiley/Wrox Employee
__________________
Hal Levy
 
Old October 30th, 2003, 02:57 PM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 839
Thanks: 0
Thanked 1 Time in 1 Post
Default

Just a few efficiency observations, in no particular order:

1. That CROSS JOIN can do it to you.

2. First thing to look at is the query execution plan. See if any table scans are being done. If so, make sure that indexes and/or foreign key constraints are present on all columns involved in the JOIN expressions and WHERE clauses. This has to be tempered, though, on how much updating/inserting/deleting is going on in these tables, as indexes must be maintained whenever these operations are done, so it you have a lot of indexes, these operations will slow down. It's a balancing act.

3. By default the UNION operator removes duplicate rows, and UNION ALL keeps them, so I find it interesting that you are using SELECT DISTINCT to remove duplicates, then using UNION ALL to keep them.

4. The BETWEEN operator is inclusive of its end points, so your WHERE clauses have redundant expressions in them.

Beyond this cursory look, we'll have to get into table structure and what you are trying to accomplish...

Jeff Mason
Custom Apps, Inc.
www.custom-apps.com
 
Old October 31st, 2003, 11:50 AM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 1,101
Thanks: 0
Thanked 2 Times in 2 Posts
Default

Jeff,

This is a job that was outsourced before I got here. I am not particularly happy with the table design or the quality of the stored procs. Of course, I am not a DBA so optimization and complex querys are beyond me.

They re-did the SP overnight and it now runs in 2 seconds (versus 2 minutes). When looking at the execution plan for the old SP there was a point where there was 40 MILLION rows.. With the data quantity I had, this was clearly a cartesian product from a bad join...

Some of the points you make, however, are still valid.. I am pasting the new SP here...

Perhaps some day I'll be good enough with SQL to follow this :)


Code:
CREATE  PROCEDURE dbo.PDIDC_rpt_OptimalFreq

    (
        @startdt datetime,
        @enddt datetime,
        @terrid nvarchar(8)
    )

AS
    SET NOCOUNT ON 
    SELECT t_CallInstance.PDIControlID, t_Target.PhysicianFirstName, t_Target.PhysicianLastName, 
t_DetailOrder.ProductID, t_TargetFrequency.Frequency, t_DetailOrder.DetailOrder
FROM         t_TargetFrequency INNER JOIN
                      t_Target ON t_TargetFrequency.PdiControlID = t_Target.PDIControlID INNER JOIN
                      t_DetailOrder ON t_TargetFrequency.ProductID = t_DetailOrder.ProductID INNER JOIN
                      t_CallInstance ON t_Target.PDIControlID = t_CallInstance.PDIControlID AND t_DetailOrder.CallInstanceID = t_CallInstance.CallInstanceID AND 
                      t_DetailOrder.CallInstanceID = t_CallInstance.CallInstanceID
WHERE     (t_CallInstance.TerritoryID = @terrid) AND (t_CallInstance.CallDate between @startdt and @enddt OR t_CallInstance.CallDate = @startdt OR t_CallInstance.CallDate = @enddt) 
UNION ALL
SELECT DISTINCT
                      t_target.PDIControlID, t_target.PhysicianFirstName, t_target.PhysicianLastName, t_TargetFrequency.ProductID, t_TargetFrequency.Frequency, 0 as DetailOrder
FROM         t_Target INNER JOIN
              t_TargetFrequency ON t_target.PDIControlID = t_TargetFrequency.PdiControlID 
                      CROSS JOIN t_Location lc 
WHERE     (lc.Territory = @terrid ) AND (t_target.PDIControlID = lc.PDIControlID) AND (t_Target.PDIControlID NOT IN(SELECT t_CallInstance.PDIControlID from t_CallInstance where (t_CallInstance.TerritoryID = @terrid) AND (t_CallInstance.CallDate between @startdt and @enddt OR t_CallInstance.CallDate = @startdt OR t_CallInstance.CallDate = @enddt))) 
ORDER BY t_Target.PhysicianLastName, t_CallInstance.PDIControlID ASC 
    RETURN
GO
Hal Levy
Web Developer, PDI Inc.

NOT a Wiley/Wrox Employee





Similar Threads
Thread Thread Starter Forum Replies Last Post
vbNullString and optimizing Classic ASP crmpicco Classic ASP Basics 3 February 10th, 2006 10:00 PM
Optimizing CrystalReportViewer imcoolanytime Crystal Reports 0 February 6th, 2006 11:15 AM
Optimizing ASP Page anandham Classic ASP Databases 1 August 22nd, 2005 12:03 AM
Optimizing search in a xml document roy XML 2 September 23rd, 2003 05:17 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.