-2

我有以下查询..

SELECT avg(h.price)
FROM `car_history_optimized` h
LEFT JOIN vin_data vd ON (concat(substr(h.vin,1,8),'_',substr(h.vin,10,3))=vd.prefix)
WHERE h.date >='2015-01-01'
  AND h.date <='2015-04-01'
  AND h.dealer_id <> 2389
  AND vd.prefix IN
    (SELECT concat(substr(h.vin,1,8),'_',substr(h.vin,10,3))
     FROM `car_history_optimized` h
     LEFT JOIN vin_data vd ON (concat(substr(h.vin,1,8),'_',substr(h.vin,10,3))=vd.prefix)
     WHERE h.date >='2015-03-01'
       AND h.date <='2015-04-01'
       AND h.dealer_id =2389)

它找到过去 3 个月内除 (2389) 以外的其他所有人销售的汽车的平均市场价值,但仅查找 (2389) 销售的具有相同品牌、型号的汽车

上面的查询可以优化吗?运行 1100 万条记录需要 2 分钟。

谢谢

4

3 回答 3

1

您多久使用一次特定的“前缀”?如果经常,那么我将指导您对“虚拟”列进行索引。

否则,你需要

INDEX(date)             -- for the outer query
INDEX(dealer_id, date)  -- for what is now the subquery

然后EXISTS按照建议进行操作,或使用LEFT JOIN ... WHERE ... IS NULL.

date一个DATE?还是一个DATETIME?您可能会包括额外的一天。建议这种模式:

WHERE date >= '2015-01-01'
  AND date  < '2015-01-01' + INTERVAL 3 MONTH
于 2016-01-06T00:10:07.600 回答
0

我建议3件事

  1. 添加一列并对其进行索引(避免连接中的函数)
  2. 使用内连接
  3. 使用 EXISTS (...) 而不是 IN (...)

要“优化”该查询,您需要在car_history_optimized包含结果的表中添加一列,concat(substr(vin,1,8),'_',substr(vin,10,3))并且该列应该被索引。

另外,使用 INNER JOIN。在当前查询中,左外连接被浪费了,因为您要求该表的每一行都是 IN(子查询),因此不允许该表中的 NULL,因此您具有与内连接相同的效果。

使用 EXISTS 而不是 IN

SELECT
      AVG(h.price)
FROM car_history_optimized h
      INNER JOIN vin_data vd ON h.new_column = vd.prefix
WHERE h.`date` >= '2015-01-01'
      AND h.`date` <= '2015-04-01'
      AND h.dealer_id <> 2389
      AND EXISTS (
            SELECT
                  NULL
            FROM car_history_optimized cho
            WHERE cho.`date` >= '2015-03-01'
                  AND cho.`date` <= '2015-04-01'
                  AND cho.dealer_id = 2389
                  AND vd.prefix = cho.new_column
      )
;

顺便一提:

  • 我假设已经有一些索引,其中包括datedealer_id
  • 将来避免使用“日期”作为列名(这是一个保留字)
于 2016-01-06T00:00:01.700 回答
0

如果你想要一个简单的解决方案,我最初的想法是想办法在你的连接中不调用函数。

您会对索引有用的机会产生负面影响。

(concat(substr(h.vin,1,8),'_',substr(h.vin,10,3))=vd.prefix)

也许like语句会是一个更好的主意,但是,应避免使用连接子句中的任何一种方法。

底线是您的表结构和关系在这里留下了改进的空间......如果您需要,concat因为您避免加入中间表,请不要 - 允许使用索引,它应该会提高您的查询性能。

另外,请确保您有索引。

于 2016-01-05T21:58:10.603 回答