【问题标题】:Query Optimization - <Derived 2> Type: ALL, Key = NULL查询优化 - <Derived 2> 类型:ALL,Key = NULL
【发布时间】:2015-12-03 10:49:28
【问题描述】:

有人提出了类似的问题,我已针对每条建议重新编写了此查询,但无法找出问题所在。当向 EXPLAIN EXTENDED 提交以下查询时,我同时收到 'Type' = 'ref' 并且为每个表找到了一个键(尽管我不知道为什么 'isActive' 是为派生表 'CS' 选择的键。

SELECT 
    distinct
    CS.BLNUMBER
    ,CS.CONTAINER
    ,s.status
    #,s.location
    #,s.dateandtime 
FROM 
    CUSTOMERSHIPMENTS CS
INNER JOIN SHIPMENTS S 
    ON CS.BLNUMBER = S.BLNUMBER 
    AND CS.CONTAINER = S.CONTAINERNUMBER
WHERE
    cs.blnumber <>''
    and CS.CDATE > NOW() - INTERVAL 3 MONTH 
    and CS.ISACTIVE = 1
    and cs.hostcompany_id = cs.company_id
    AND S.STATUS <> ''

当我为这个联接分配一个别名并再次加入“customershipments”表时,这次称为“CS2”,如下所示:

FROM
(
SELECT 
    distinct
    CS.BLNUMBER
    ,CS.CONTAINER
    ,s.status
    #,s.location
    #,s.dateandtime 
FROM 
    CUSTOMERSHIPMENTS CS
INNER JOIN SHIPMENTS S 
    ON CS.BLNUMBER = S.BLNUMBER 
    AND CS.CONTAINER = S.CONTAINERNUMBER
WHERE
    cs.blnumber <>''
    and CS.CDATE > NOW() - INTERVAL 3 MONTH 
    and CS.ISACTIVE = 1
    and cs.hostcompany_id = cs.company_id
    AND S.STATUS <> ''
) temp

INNER JOIN CUSTOMERSHIPMENTS CS2 
ON temp.blnumber = CS2.BLNUMBER
and temp.container = cs2.container

EXPLAIN EXTENDED 现在立即告诉我:

id  select_type table   type    possible_keys   key key_len ref rows    filtered    Extra
1   PRIMARY derived2    ALL NULL    NULL    NULL    NULL    45120   100.00  Using temporary

但是“Derived2”指向 EXPLAIN EXTENDED ID 的 2,它是我在 CS 和 S 之间的连接。它是如何从有钥匙变成找不到钥匙的?我想不通。

【问题讨论】:

  • 什么版本的 MySQL? 5.6 有一些子查询的改进; 5.7 有更多。

标签: mysql optimization derived explain


【解决方案1】:

子查询没有索引。 (见脚注。)因此,建议先计划运行子查询,然后再计划JOINing 到其他表。在您的情况下,cs2 需要复合 INDEX(BLNUMBER, container)(以任意顺序)。

以下是整个查询的执行方式:

  1. 执行子查询,将结果存储到临时表中(Engine MEMORYMyISAM)。
  2. JOINCS2 使用 BLNUMBER 和/或 container 的任何可能。

同时,子查询的最优索引是

  • CS: (ISACTIVE, CDATE) -- 更多内容如下
  • S: (BLNUMBER, CONTAINERNUMBER)

请提供SHOW CREATE TABLE 和所有EXPLAIN。让我再猜猜……

你说INDEX(isactive)被神秘选中了?如果不到 20% 的表有 CS.ISACTIVE = 1,那将是一个有用的索引。是这样吗?无论如何,我建议的综合指数会更好。

子查询中是否有大约 45K 行?这需要时间来生成和使用。

脚注:在 5.6 中,优化器发现每个子查询的最佳索引应该是什么,并将其添加到 tmp 表中。但是,如果CS2 具有我上面提到的索引,这可能无关紧要。 JOIN 可以采用任何一种方式,那么为什么还要在 temp 上创建一个并不比 CS2 上的索引更好的索引。

【讨论】:

  • 您说子查询不使用索引,但在脚注中它说“优​​化器发现每个子查询的最佳索引应该是什么。”我确实有一个用于 cs 和 cs2 的索引(BLNumber,Container)。我相信其他事情正在发生。当我运行查询大约需要 12 分钟,但返回“查询耗时 0.065 秒”。我不知道该怎么做!我的 CPU 在 m3.xlarge amazon MYSQL RDS 上整周都没有超过 50%。不过,您的解释很棒,我认为它会帮助我解决这个问题和其他问题。
  • 您是否打开了“查询缓存”? (SHOW VARIABLES LIKE 'query%';)
  • 5.6 会添加索引;以前的版本不会。你用的是哪个版本?
  • - V5.6.23 - 查询缓存:我不希望结果数据集“永远”相同。
  • 然后我也被千倍的加速所难倒。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-26
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多