Запрос мне нужно ускорить - PullRequest
1 голос
/ 12 октября 2009

У меня есть этот запрос в 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) -.

SQL для UDF находится здесь:

    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 ]

5 голосов
/ 12 октября 2009
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 голос
/ 12 октября 2009

Я работаю над этим, так что я не пробовал это. Но я думаю, что вы могли бы сделать это, чтобы удалить функцию. Замените вызов функции этими двумя предложениями. Предполагается, что «Доставлено» является 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, я предполагаю, что вы ищете, существует ли работа, и все ли выполнено с этой работой. поэтому, если есть хоть одна вещь, которая не была доставлена, ее необходимо исключить.

Как уже упоминалось: от макушки головы, и, следовательно, не проверено или не профилировано. Я думаю, что я правильно понял логику. Если нет, то должен быть его простым вариантом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...