这个查询可以优化吗?

时间:2016-02-05 21:11:46

标签: mysql sql database

我有一个带有以下列的表的mysql数据库..

id
dealerId
month_year
total_price
total_count
vin_prefix

和表有2000万条记录,我希望获得ID为#02的经销商销售的所有汽车的总和(total_price)(这很简单)

但是,我希望得到所有其他经销商的总和,这些经销商与经销商#02

一样销售与vin_prefix相同的汽车

所以我写了这个查询...

SELECT d.dealerId 
    FROM `dealer_monthly_report` d 
    where d.dealerId <> 2 
        and d.vin_prefix in (select distinct(d2.vin_prefix) 
                                 from `dealer_monthly_report` d2   
                                 where d2.dealerId = 2) 
    group by d.dealerId

但是我们可以以任何方式优化此查询吗? 索引已分别用于dealerId,vin_prefix和month_year。

谢谢!

2 个答案:

答案 0 :(得分:1)

刚尝试了1.000.000记录的查询和Gordon的查询。通过添加索引dealer_monthly_report(vin_prefix, dealerId),您建议的查询似乎比Gordon的查询快一点(我的记录大约1-2秒)。

编辑:更正了临时表的代码

我建议将Gordon的第一个解决方案扩展如下:

CREATE TEMPORARY TABLE vin_prefixes_dealerID_2
    SELECT distinct(d.vin_prefix) as vin_prefix
    FROM `dealer_monthly_report` d
    WHERE d.dealerID = 2
;

SELECT d.dealerId, sum(total_price)
FROM `dealer_monthly_report` d
WHERE d.dealerId <> 2 AND
EXISTS (
    SELECT 1 
    FROM `vin_prefixes_dealerID_2` d2
    where d.vin_prefix = d2.vin_prefix
)
GROUP BY d.dealerId;

这将查询时间从最初的18-20秒减少到大约6-7秒(对于1.000.000条记录)

修改:更正了替代方法

替代方法可能是:

CREATE TEMPORARY TABLE vin_prefixes_dealerID_2
    SELECT distinct(d.vin_prefix) as vin_prefix
    FROM `dealer_monthly_report` d
    WHERE d.dealerID = 2
;

SELECT d.dealerId, sum(d.total_price)
FROM `dealer_monthly_report` d
JOIN `vin_prefixes_dealerID_2` d2
ON d.vin_prefix = d2.vin_prefix
WHERE d.dealerID <> 2
GROUP BY d.dealerId;

这将处理时间缩短到大约0.91(!!!)秒

答案 1 :(得分:0)

是的,它可能是。这是您的查询:

SELECT d.dealerId
FROM `dealer_monthly_report` d 
WHERE d.dealerId <> 2 AND
      d.vin_prefix in (select distinct d2.vin_prefix
                       from `dealer_monthly_report` d2
                       where d2.dealerId = 2
                      ) 
GROUP BY d.dealerId;

我会使用exists重新编写查询:

SELECT d.dealerId
FROM `dealer_monthly_report` d 
WHERE d.dealerId <> 2 AND
      EXISTS (select 1
              from `dealer_monthly_report` d2
              where d2.dealerId = 2 and d.vin_prefix = d2.vin_prefix
             ) 
GROUP BY d.dealerId;

然后,dealer_monthly_report(dealerId)dealer_monthly_report(vin_prefix, dealerId)上的索引最适合提高效果。

如果您有vin_prefix的经销商表,那么最佳方法根本没有group by

select dealerId d
from dealers d
where dealerid <> 2 and
      exists (select d2.vin_prefix
              from `dealer_monthly_report` dmr
              where d2.dealerId = 2 and dmr.vin_prefix = d.vin_prefix
             );

这将使用dealer_monthly_report(vin_prefix, dealerId)dealers(dealerid, vin_prefix)上的索引。