【问题标题】:How to improve the performance of this query that spans across multiple databases?如何提高跨多个数据库的查询的性能?
【发布时间】:2011-07-29 06:15:02
【问题描述】:

这是我用了将近 20 分钟的查询。请建议我进行更改以提高性能

SELECT DISTINCT
    CONVERT(varchar(10),x.notice_date,120)  Date,
    Y.branch_name,
    count(case when x.status='broken' and x.branch_name=y.branch_name then 1 end) 
      Broken,
    count(case when x.type='Lote' and x.branch_name=y.branch_name then 1 end)
      Lost,
    (   SELECT COUNT(A.car_no)
        FROM DB2.dbo.z_mat A
        WHERE DateAdd(Day, DateDiff(Day, 0,a.notice_date), 0)
              = DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)
          AND a.branch_name=y.branch_name
    ) mat,
    (   SELECT COUNT(B.car_no)
        FROM DB2.dbo.z_cat B
        WHERE DateAdd(Day, DateDiff(Day, 0,b.notice_date), 0)
              = DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)
          AND b.branch_name=y.branch_name
    ) cat,
    (   SELECT COUNT(C.car_no)
        FROM DB2.dbo.z_pat C
        WHERE DateAdd(Day, DateDiff(Day, 0,c.notice_date), 0)
              = DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)
          AND c.branch_name=y.branch_name
    ) pat
FROM DB1.dbo.Cars x
   , DB2.dbo.Branch Y
WHERE DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)
      > '2011-01-01'
GROUP BY CONVERT(varchar(10),x.notice_date,120)
       , DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)
       , y.branch_name

【问题讨论】:

  • 请格式化查询,使其更具可读性。尝试将外部数据获取到本地临时文件中。进行所有计算之前的表格。
  • @ARB:此时您应该已经学会了如何格式化您的帖子。它们已经被其他人不止一次地编辑过,以提高它们的表现力,为了你的利益不亚于他人的利益。我认为现在是你自己开始这样做的时候了。
  • 对不起格式错误..我试图格式化但我没有..所以我想有人得到了格式化的工作..从现在开始我会做正确的格式.. @西瓦。我正在使用 sql server 2008
  • 你能解释一下你想用所有的 DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0) 代码实现什么吗?
  • 该列实际上是日期时间..所以我将日期时间设为 2011-01-01 00:00:00.. 所以所有相同日期的日期时间都属于单一日期类别

标签: sql performance sql-server-2008


【解决方案1】:

这可能会有所帮助。试一试。

SELECT          
DISTINCT        CONVERT(VARCHAR(10), car.notice_date, 120) AS NoticeDate
            ,   brc.branch_name
            ,   COUNT(CASE WHEN car.status = 'broken'   AND car.branch_name = brc.branch_name   THEN 1 END) Broken
            ,   COUNT(CASE WHEN car.status = 'Lote'     AND car.branch_name = brc.branch_name   THEN 1 END) Lost
            ,   mat.mat_count
            ,   cat.cat_count
            ,   pat.pat_count
FROM            DB1.dbo.Cars        car
            ,   DB2.dbo.Branch      brc
CROSS APPLY     (   
                    SELECT  COUNT(mat.car_no)   mat_count
                    FROM    DB2.dbo.z_mat       mat
                    WHERE   DATEDIFF(d, mat.notice_date, car.notice_date) = 0
                    AND     mat.branch_name     = brc.branch_name
                ) mat
CROSS APPLY     (   
                    SELECT  COUNT(cat.car_no)   cat_count
                    FROM    DB2.dbo.z_cat       cat
                    WHERE   DATEDIFF(d, cat.notice_date, car.notice_date) = 0
                    AND     cat.branch_name     = brc.branch_name
                ) cat
CROSS APPLY     (   
                    SELECT  COUNT(pat.car_no)   pat_count
                    FROM    DB2.dbo.z_pat       pat
                    WHERE   DATEDIFF(d, pat.notice_date, car.notice_date) = 0
                    AND     pat.branch_name     = brc.branch_name
                ) pat
WHERE           car.notice_date > '2011-01-01'
GROUP BY        CONVERT(VARCHAR(10), car.notice_date, 120)
            ,   brc.branch_name

【讨论】:

  • 我不确定DATEDIFF(d, '2011-01-01', car.notice_date) > 0 是否使用car.notice_date 的索引。查询可能会受益于将其视为car.notice_date > '2011-01-01'(我想Cars.notice_dateDATE 类型。)
  • @Siva:谢谢。现在需要 4.20 分钟.. 你 hv 加入了 2 个表汽车和分支名称上的分支.. 但我想要的是所有通知日期和所有分支......我想要不同的通知日期,分支名称从汽车,分支......谢谢
【解决方案2】:
SELECT CONVERT(varchar(10),x.notice_date,120) Date,Y.branch_name,
COUNT(case when x.status='broken' then 1 end) Broken,
COUNT(case when x.type='Lote' then 1 end) Lost,
SUM(mat) mat, SUM(cat) cat,SUM(pat) pat
 FROM DB1.dbo.Cars x 
      JOIN DB2.dbo.Branch Y ON x.branch_name=y.branch_name
      -- group by date and branch name for z_mat table
      LEFT JOIN (select COUNT(car_no) mat,branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) notice_date from DB2.dbo.z_mat GROUP BY branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) AS a
          ON a.branch_name = y.branch_name AND DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0) = a.notice_date
      -- group by date and branch name for z_cat table    
      LEFT JOIN (select COUNT(car_no) cat,branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) notice_date from DB2.dbo.z_cat GROUP BY branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) AS b
          ON b.branch_name = y.branch_name AND DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0) = b.notice_date
      -- group by date and branch name for z_pat table        
     LEFT JOIN (select COUNT(car_no) pat,branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) notice_date from DB2.dbo.z_pat GROUP BY branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) AS c
          ON c.branch_name = y.branch_name AND DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0) = c.notice_date 
WHERE DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)>'2011-01-01' 
GROUP BY CONVERT(varchar(10),x.notice_date,120),DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0),y.branch_name

【讨论】:

  • 尝试使用 tablename.notice_date 而不是 CONVERT(varchar(10),x.notice_date,120)。如果存在,它可能会在 notice_date 取消对索引的使用
  • 更新为子查询使用左连接
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-03
  • 1970-01-01
  • 2021-08-26
  • 1970-01-01
  • 2011-01-01
  • 2011-06-30
相关资源
最近更新 更多