令人难以置信的慢查询

时间:2016-08-31 14:26:50

标签: mysql

上周我问了一个问题并合并了https://stackoverflow.com/a/39149076/6489232

下面我提出了完整的查询,这确实有效。但它的速度非常慢(最大数据库上的单个日期范围为2分钟,最小数据库为20秒),这是我在使用三重选择时的尴尬方式时的预期。

Select Sources,
Description,
Start,
Series,
Circulation,
Advert,
COG,
COF,
Orders,
ResponseP,
OrderValue,
AOV,
Marketing,
Ins,
New,
truncate((OrderValue + Ins) - (COG + COF + Marketing + Advert),2) as Profit,
truncate(((OrderValue + Ins) - (COG + COF + Marketing + Advert))/New,2) as CPN 
from
(select Sources as Sources,
 Description as Description,
 Start as Start,
 Series as Series,
 Circulation as Circulation,
 Advert as Advert,
 sum(i.itmcos) as COG,
 truncate(sum(k.stkffc)*i.itmmul,2) as COF,
 max(Orders) as Orders,
 ResponseP as ResponseP,
 max(OrderValue) as OrderValue,
 AOV as AOV,
Marketing as Marketing, 
Ins as Ins,
 New as New
  from (
        select s.soucod as Sources,
      s.soudes as Description,
      o.ordurn as ord,
      s.souexp as Ins,
      s.soudts as Start,
      s.soucir as Circulation,
      s.souser as Series,
      s.souavc as Advert, 
      count(o.ordurn) as Orders,
      sum(o.ordval) as OrderValue,
      truncate((count(o.ordurn)/s.soucir)*100,2) as ResponseP,
      truncate(sum(o.ordval)/count(o.ordurn),2) as AOV,
      truncate(sum(CASE WHEN o.ordpot = 'F' THEN o.ordval ELSE 0 END)*0.32,2) as Marketing,
      sum(CASE WHEN o.CCSCRD = m.CCSCRD then 1 else 0 end) as New
          from source s
          join orders o on o.ordsou = s.soucod
          join member m on o.ORDMEM = m.MEMKEY
      where o.ordrdt = '2016-08-30'
         group by s.soucod
       ) A
   join items i on i.ITmsou = A.Sources
   join stock k on i.itmstk = k.stkcod
 where i.itmrdt = '2016-08-30'
  group by A.Sources) B
  group by B.Sources

我必须添加第三个“选择”,因为我无法将我在第二个Select中定义的字段放入同一个选择中的计算中。以下是我希望做的可能加快这一点。

select Sources,
 Description,
 Start,
 Series,
 Circulation,
 Advert,
 sum(i.itmcos) as COG,
 truncate(sum(k.stkffc)*i.itmmul,2) as COF,
 max(Orders) as Orders,
 ResponseP,
 max(OrderValue) as OrderValue,
 AOV,
Marketing, 
Ins,
 New,
 truncate((OrderValue + Ins) - (COG + COF + Marketing + Advert),2) as Profit,
truncate(((OrderValue + Ins) - (COG + COF + Marketing + Advert))/New,2) as CPN 
  from (
        select s.soucod as Sources,
      s.soudes as Description,
      o.ordurn as ord,
      s.souexp as Ins,
      s.soudts as Start,
      s.soucir as Circulation,
      s.souser as Series,
      s.souavc as Advert, 
      count(o.ordurn) as Orders,
      sum(o.ordval) as OrderValue,
      truncate((count(o.ordurn)/s.soucir)*100,2) as ResponseP,
      truncate(sum(o.ordval)/count(o.ordurn),2) as AOV,
      truncate(sum(CASE WHEN o.ordpot = 'F' THEN o.ordval ELSE 0 END)*0.32,2) as Marketing,
      sum(CASE WHEN o.CCSCRD = m.CCSCRD then 1 else 0 end) as New
          from source s
          join orders o on o.ordsou = s.soucod
          join member m on o.ORDMEM = m.MEMKEY
      where o.ordrdt = '2016-08-30'
         group by s.soucod
       ) A
   join items i on i.ITmsou = A.Sources
   join stock k on i.itmstk = k.stkcod
 where i.itmrdt = '2016-08-30'
  group by A.Sources

但由于未知字段而失败,显然是在该选择中创建的COF,COG等字段。所以我添加了第三个选择来做更高的阶段。如果不需要第三个选择,有没有办法做到这一点?

1 个答案:

答案 0 :(得分:-1)

我可以建议 - 在第一步 - 创建一个SQL"视图":

CREATE VIEW view_name AS
select s.soucod as Sources,
s.soudes as Descrption,
o.ordurn as ord, (etc...),
o.ordrdt -- add this column intending to use it in where clause later
FROM source s JOIN orders o ON o.ordsou = s.soucod
JOIN member m ON o.ORDMEM = m.MEMKEY
GROUP BY s.soucod;

您可以查看此链接,了解SQL视图如何提升效果:MySql views performance

假设所有数据库必须正确编入索引

然后,您的最终查询可能如下所示:

SELECT sources, description (etc...)
FROM view_name A
JOIN items i ON i.ITmsou = A.Sources
JOIN stock k ON i.itmstk = k.stkcod
WHERE i.itmrdt = '2016-08-30' AND A.ordrdt = i.itmrdt
GROUP BY A.Sources;

这将执行" GROUP BY"在该查询中只有一次。第一个" GROUP BY"由视图预先执行。许多GROUP BY与" COUNT,SUM ..."并且所有计算出的语句通常都很慢。