查询我需要加快速度

时间:2009-10-12 14:58:45

标签: sql sql-server tsql

我在SQL Server 2005中有这个查询:

SELECT J.JobID, 
       dbo.tblCustomers.Name AS CustomerName, 
       J.CustomerJobNumber, 
       J.JobName, 
       (CASE WHEN [tblCustomers].[CoreCust] = 0 THEN 'AUXILIARY' ELSE 'CORE' END) AS Department, 
       J.JobStatusID, 
       dbo.tblJobTypes.JobType
  FROM dbo.tblJobs (NOLOCK) AS J 
INNER JOIN dbo.tblCustomers (NOLOCK) ON J.CustomerID = dbo.tblCustomers.CustomerID
INNER JOIN dbo.tblJobTypes (NOLOCK) ON J.JobTypeID = dbo.tblJobTypes.JobTypeID
INNER JOIN dbo.tblDepartments (NOLOCK) ON J.DepartmentId = dbo.tblDepartments.DepartmentID
WHERE (J.Closed = 0) 
  AND (J.Invoiced = 0) 
  AND (J.Active = 1) 
  AND (dbo.fncIsAllPointsDelivered(J.JobID) = 1) 
  AND (J.DepartmentId <> 2)

此查询运行时间太长,我知道问题是UDF - (dbo.fncIsAllPointsDelivered(J.JobID)= 1) - 。

UDF的SQL在这里:

    DECLARE @DetailCount int
    DECLARE @TrackingCount int

    SELECT @DetailCount = COUNT(*)
      FROM [dbo].[tblLoadDetails] (NOLOCK)
     WHERE JobId = @JobId

    SELECT @TrackingCount = COUNT(*)
      FROM [dbo].[tblLoadDetails] (NOLOCK)
     WHERE JobId = @JobId AND Delivered = 1

    IF(@DetailCount = @TrackingCount AND @DetailCount > 0)
      RETURN 1

    RETURN 0

除非作业中包含大量的装载细节,否则所有这些都会非常快速地运行。我试图想办法让UDF更快或摆脱UDF的需要,但我不知所措。我希望你们中的一些SQL大师能够帮助我。

2 个答案:

答案 0 :(得分:5)

SELECT  *
FROM    tblJobs j
INNER JOIN
        tblCustomers c
ON      c.CustomerID = J.CustomerID
INNER JOIN
        tblJobTypes jt
ON      jt.JobTypeID = J.JobTypeID
INNER JOIN
        tblDepartments d
ON      d.DepartmentID = J.DepartmentId
WHERE   J.Closed = 0
        AND J.Invoiced = 0
        AND J.Active = 1
        AND J.DepartmentId <> 2
        AND J.JobID IN
        (
        SELECT  JobID
        FROM    tblLoadDetails
        )
        AND J.JobID NOT IN
        (
        SELECT  JobID
        FROM    tblLoadDetails
        WHERE   Delivered <> 1
        )

在这些字段上创建综合索引:

tblJobs (Closed, Invoiced, Active) INCLUDE (DepartmentID)

如果您的tblLoadDetails.Delivered是位字段,则创建以下索引:

tblLoadDetail (JobID, Delivered)

并重写最后一个条件:

SELECT  *
FROM    tblJobs j
INNER JOIN
        tblCustomers c
ON      c.CustomerID = J.CustomerID
INNER JOIN
        tblJobTypes jt
ON      jt.JobTypeID = J.JobTypeID
INNER JOIN
        tblDepartments d
ON      d.DepartmentID = J.DepartmentId
WHERE   J.Closed = 0
        AND J.Invoiced = 0
        AND J.Active = 1
        AND J.DepartmentId <> 2
        AND
        (
        SELECT  TOP 1 Delivered
        FROM    tblLoadDetails ld
        WHERE   ld.JobID = j.JobID
        ORDER BY
                Delivered
        ) = 1

答案 1 :(得分:1)

我是从头顶开始工作的,所以我没有试过这个。但我认为你可以这样做来删除这个功能。用这两个子句替换对函数的调用。这假设'Delivered'是一个BIT字段:

AND EXISTS (SELECT 1 FROM tblLoadDetails WHERE JobID = J.JobID)
AND NOT EXISTS (SELECT 1 FROM tblLoadDetails WHERE JobID = J.JobID AND Delivered = 0)

AND EXISTS涵盖UDF的@DetailCount > 0检查;然后,AND NOT EXISTS涵盖了@ DetailCount = @TrackingCount,我所做的假设是,您正在查看作业是否存在以及是否已完成该作业。所以,如果有一件事情尚未交付,则需要将其排除在外。

如上所述:从头顶开始,因此没有经过测试或未进行过剖析。我想我的逻辑是正确的。如果没有, 应该是的简单变体。