【问题标题】:mysql "distinct query" from 3 table performs slow on big data来自 3 个表的 mysql "distinct query" 在大数据上执行缓慢
【发布时间】:2017-02-15 03:19:24
【问题描述】:

这里是三个表,order,order_record,pay,有近2300000条记录。

给定1个order_id时pay table会有多于1条记录,所以我需要使用DISTINCT去除重复的结果

现在我需要从 order_id 上的这三个表连接中获取不同的数据,下面的示例查询 sql:

SELECT
    DISTINCT (a.order_id)
    a.order_id,a.user_id
    b.boss_order_id,
    c.pay_id,

    FROM order a
    LEFT JOIN order_record b ON a.order_id = b.order_id AND b.is_delete IN (0,1)
    LEFT JOIN pay c ON a.order_id = c.order_id AND c.is_delete =0  WHERE 1=1 AND a.is_delete IN (0,1)
    ORDER BY a.id DESC LIMIT 0, 10

此查询将花费大量时间。 然后我改用“GROUP BY”:

SELECT

    a.order_id,a.user_id
    b.boss_order_id,
    c.pay_id,

    FROM order a
    LEFT JOIN order_record b ON a.order_id = b.order_id AND b.is_delete IN (0,1)
    LEFT JOIN pay c ON a.order_id = c.order_id AND c.is_delete =0  WHERE 1=1 AND a.is_delete IN (0,1)
    GROUP BY a.order_id
    ORDER BY a.id DESC LIMIT 0, 10

这次查询需要 122 秒。

有没有更快的实现方式?

【问题讨论】:

  • 您是否在列上设置了索引?
  • 请添加您的表结构(带索引)以及查询的解释说明。
  • 第二个查询无效,因为您选择的是非聚合列。而DISTINCT 经常使用GROUP BY 作为实现,所以两者的行为应该相似。以上关于索引的评论是相关的。
  • @FreedomPride 是的
  • @JorgeCampos 抱歉,我无法给出结构。我的查询的基本内容是查询存储在 order/order_record/pay 表中的订单数据的限制数量,有序,没有重复

标签: mysql distinct


【解决方案1】:

您使用的是left join。因此,您可以这样做:

SELECT o.order_id, o.user_id, orr.boss_order_id, p.pay_id,
FROM (SELECT o.*
      FROM order o
      WHERE o.is_delete IN (0, 1)
      ORDER BY o.id DESC
      LIMIT 10
     ) o LEFT JOIN
     order_record orr
     ON o.order_id = orr.order_id AND
        orr.is_delete IN (0, 1) LEFT JOIN
     pay p
     ON o.order_id = p.order_id AND
        p.is_delete = 0 
WHERE 1=1 AND o.is_delete IN (0, 1)
GROUP BY o.order_id
ORDER BY o.id DESC
LIMIT 0, 10

您错误地使用了GROUP BY,因为您在SELECT 中有未在GROUP BY 中的未聚合列。

【讨论】:

  • 非常感谢!它有效,我从你的答案中得到了关键:获取表 order 中的限制数量记录,然后对表 order_record 进行联接查询并支付,我在订购和限制结果之前进行了联接查询。
  • 这里还有个问题,如果我想在limit 10前面加orr.boss_order_id>'xxxx'怎么办?
  • @halfdark 。 . .将其添加到第二个on 子句中,其中orr 已经具有条件。
  • 我的意思是在此之前。`(SELECT o.* FROM order o WHERE o.is_delete IN (0, 1) ORDER BY o.id DESC LIMIT 10)`,因为这个sql已经先limit了表顺序 10 条记录
【解决方案2】:

另一种方法让 where 子句完成大部分工作:

select ...
from order
left join order_using using (order_id)
...
where
order.order_id < (select max(order_id) from orders order by order_id limit 10) ...
limit 10

最终限制 10 很奇怪,因为如果您放弃分组,您可能会从订单中获得部分记录。 IE。你可能想放弃它,然后只放一个限价订单表。使用 group by 意味着您将从表 b 和 c 中获取随机数据,除非您使用聚合函数告诉 mysql 您想要哪个行值。

【讨论】:

    猜你喜欢
    • 2020-10-04
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 2015-01-28
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多