【问题标题】:MySql select from subquery slow (even though subquery on it's own is fast)MySql 从子查询中选择慢(即使它自己的子查询很快)
【发布时间】:2011-07-24 03:56:12
【问题描述】:

我正在尝试加快查询速度:

SELECT order.id
    FROM (
     SELECT o.id 
     FROM `order` as `o` 
     INNER JOIN order_item as oi on
        oi.order_id = o.id
        AND `o`.`canceled` = 0
        AND ( `o`.`return_date` > "2011-03-14" OR oi.checked = 0 OR '2011-03-14' < oi.last_update)
    ) as `order`

时钟为 0.0930 秒。子查询 (SELECT * FROM order as o...) 在它自己的时钟上为 0.0005 秒。我正在测试的表大约有 10000 行,其中 43 行从子查询 where 子句返回。

除了加快查询速度之外,如果有人能向我解释为什么当我将它包装在另一个查询中时查询会变慢 100 倍以上,我真的很高兴?

MySql 解释告诉我它自己的子查询首先选择o,然后选择oi。 MySql 解释整个查询首先选择(什么是derived2?),然后依次选择ooi

我希望子查询成为子查询,因为我正在执行很多不在 where 子句中的连接(我已将其从代码和基准测试中排除)。如果我自己使用子查询和连接,查询会更慢。

任何帮助将不胜感激。我已经搜索了答案但找不到答案,这可能只是因为我不知道要寻找什么,如果是这样,我深表歉意。

【问题讨论】:

    标签: mysql select subquery


    【解决方案1】:

    MySQL 在对内联视图进行任何操作之前对其进行缓冲。

    0.0006 您在第一个查询中看到的秒数很可能是响应时间(获取的第一行),而不是总时间(获取的最后一行)。

    如果idPRIMARY KEY 上的order 表,则不需要GROUP BY

    如果您每个订单有很多商品(平均每个订单超过20 个商品左右),您可以尝试创建以下索引:

    order_item (order_id, checked)
    order_item (order_id, last_update)
    

    并将您的相关子查询一分为二:

    SELECT  *
    FROM    order o
    WHERE   o.canceled = 0
            AND
            (
            o.return_date > '2011-03-14'
            OR
            (
            SELECT  MIN(checked)
            FROM    order_item oi
            WHERE   order_id = o.id
            ) = 0
            OR
            (
            SELECT  MAX(last_update)
            FROM    order_item oi
            WHERE   oi.order_id = o.id
            ) > '2011-03-14'
            )
    

    同样,这仅在您每个商品有很多订单时才有用,否则对所有订单进行一次扫描会更有效率。

    【讨论】:

    • 我已经改变了查询,你可以看到一点(这种新方法更快),但你的回答真的很有帮助。我一直在拔头发,因为我在想包装子查询会使它变得非常慢,尽管正如你所说的那样,它自己的子查询似乎更快,因为响应时间仅适用于第一行。感谢您帮助我理解这一点!我认为我需要保留“分组依据”,因为我正在执行我已从示例(和基准测试)中排除的连接和 group_concats。
    【解决方案2】:
    1. 检查索引
    2. 您是否优化了正在使用的表?
    3. 如果您将 SELECT 语句中的“*”更改为您需要的列的实际名称,查询将更快地运行。
    4. 您是否需要多个 GROUP BY “订单 ID” - 一个在另一个中?

    【讨论】:

    • 1.我应该寻找什么?我已经研究过了,但无法提出任何改进。 2. MySql 说它无法优化表,它确实重新创建了它们。不幸的是,它没有帮助。 3. 我“手动”选择字段,我只是在处理这个问题时简化了查询。
    • 1. “订单”需要在“id”和“order_item”上有索引 - 在“order_id”上
    • 1. (我正在使用 MySql 工作台)。 Order.id 有两个索引,类型 PRIMARY 和 UNIQUE,order_item.order_id 有一个索引类型 INDEX。
    • 也尝试删除“WHERE 1”,这可能会缩短一点时间。
    • 请参见 4. 尝试删除第一个和第二个“GROUP BY”,只保留最后一个。
    猜你喜欢
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-30
    • 1970-01-01
    相关资源
    最近更新 更多