如何减少SQL Select Query的执行时间

时间:2016-08-20 12:20:09

标签: sql sql-server

TitemName和TshotName是这里的问题

SELECT DISTINCT
    tJobs.* ,
    tCustomer.Name AS Customer_name ,
    (SELECT tEmployee.First + ' ' + tEmployee.Last
     FROM tEmployee
     WHERE tEmployee.EmployeeID = tJobs.AccountExecutiveID) AS AccountExecutive,
    (SELECT tEmployee.First + ' ' + tEmployee.Last
     FROM tEmployee
     WHERE tEmployee.EmployeeID = tJobs.AccountManagerID) AS AccountManager,
    dbo.RetrunUserFavourite(tJobs.JobNumber, 33369, 'Employee') AS Favorites,
    (SELECT COUNT(*)
     FROM tShots
     WHERE tShots.JobNumber = tJobs.JobNumber) AS shotcount,
    SUBSTRING((SELECT  ', ' + SKU + ', ' + Source + ', ' + ModelNumber
                            + ', ' + Description
               FROM tItems
               WHERE tItems.CustomerID = tCustomer.CustomerID
               FOR XML PATH('')), 3, 200000) titemName,
    SUBSTRING((SELECT  ', ' + ArtDirection + ', '
                            + REPLACE(CONVERT(VARCHAR(5), AdDate, 110), '-',
                                      '/')
               FROM tShots
               WHERE tShots.JobNumber = tJobs.JobNumber
               FOR XML PATH('')), 3, 200000) TshotName
FROM    
    tJobs
INNER JOIN 
    tCustomer ON tCustomer.CustomerID = tJobs.CustomerID
WHERE
    tCustomer.CustomerID = 68666

2 个答案:

答案 0 :(得分:1)

你的查询中有很多字符串操作,无论如何,查询的略微改进版本看起来像......

Select DISTINCT
        tJobs.*
      , tCustomer.Name              AS Customer_name
      , AE.First + ' ' + AE.Last    AS AccountExecutive
      , AM.First + ' ' + AM.Last    AS AccountManager
      , dbo.RetrunUserFavourite(tJobs.JobNumber,33369,'Employee')AS Favorites
      , TS.shotcount
      , SUBSTRING(( SELECT ', ' + SKU + ', ' + Source + ', ' + ModelNumber+ ', ' + Description 
                    FROM tItems 
                    where tItems.CustomerID=tCustomer.CustomerID 
                    FOR XML PATH('')), 3, 200000)titemName
     , SUBSTRING(( SELECT ', ' +  ArtDirection +', '+REPLACE(CONVERT(VARCHAR(5),AdDate,110), '-','/') 
                   FROM tShots 
                   where tShots.JobNumber=tJobs.JobNumber 
                   FOR XML PATH('')), 3, 200000)TshotName
From  tJobs 
inner join tCustomer on tCustomer.CustomerID = tJobs.CustomerID
Left join tEmployee AE ON AE.EmployeeID = tJobs.AccountExecutiveID
Left join tEmployee AM ON AM.EmployeeID = tJobs.AccountManagerID
Left join (
            SELECT JobNumber , Count(*) shotcount
            FROM tShots 
            GROUP BY JobNumber
          ) TS  ON TS.JobNumber = tJobs.JobNumber
WHERE tCustomer.CustomerID = 68666 

几个指针:

  1. 在select语句中使用子查询会使效率非常低,因为子查询是针对外部查询返回的每一行执行的,更合理的方法是使用连接。

  2. 您还在select中调用了用户定义的标量函数dbo.RetrunUserFavourite(),这些标量UDF也是性能杀手,同样在这里应用相同的执行逻辑,它们也为每个执行外部查询返回的行,更明智的方法是将函数逻辑/代码放入CTE并将查询连接到该CTE。

  3. 您为最后两列动态创建的这些以逗号分隔的列表将会很慢,也许内联表值函数可以在此处提供更好的性能。

答案 1 :(得分:1)

我非常同意M Ali的评论。我要说两点。第一个不是关于性能。但是,而不是substring()使用:

  STUFF((SELECT ', ' + SKU + ', ' + Source + ', ' + ModelNumber+ ', ' + Description 
         FROM tItems 
         WHERE tItems.CustomerID = tCustomer.CustomerID 
         FOR XML PATH('')
        ), 1, 1, '') as titemName

这样,你就不需要在代码中浮动的奇怪的,没有意义的数字。

其次,您可能需要索引。基于突出的性能问题,我建议:

tItems(CustomerID)

tshots(JobNumber, ArtDirection, AdDate)