MySQL:长时间运行的 LEFT JOIN 查询性能

标签 mysql sql join query-optimization query-performance

一个 MySQL 数据库包含两个表:customercustmomer_orders

customer 表包含 8000 万个条目并包含 80 个字段。其中一些我感兴趣:

  1. Id (PK, int(10))
  2. 位置(varchar 255,可为空)。
  3. Registration_Date(日期时间,可为空)。索引。

customer_orders 表包含 4000 万条条目,仅包含 3 个字段:

  1. Id (PK, int(10))
  2. Customer_Id(int(10),FK 到客户表)
  3. Order_Date(日期时间,可为空)

当我运行这样的查询时,它需要 ~800 秒来执行并返回 4000 万个条目:

SELECT o.* 
FROM customer_orders o
LEFT JOIN customer c ON (c.Id = o.Customer_Id) 
WHERE NOT (ISNULL(c.Location)) AND c.Registration_Date < '2018-01-01 00:00:00';

装有 MySQL 服务器的机器有 32GB 内存,其中 28GB 分配给 MySQL。 MySQL版本:5.6.39。

MySQL在记录量这么大的表上执行这么长时间的查询正常吗? 我怎样才能提高性能?

更新:

customer_orders 表不包含我们想要存储的任何重要数据。它是某种复制表,其中包含最近 10 天内的订单。 我们每天都运行一个存储过程,该过程会删除交易范围内超过 10 天的订单。

在某个时刻,这个存储过程由于没有优化查询而超时,订单数量每天都在增长。 先前的查询还包含 COUNT 方法,我想这超过了超时。

然而,令我惊讶的是,MySQL 最多可能需要 15 分钟才能在附加条件下获取 40m 条记录。

最佳答案

我觉得很正常。如果你分享什么会很有帮助 explain该查询的返回值。

为了优化查询,从 customer_orders 开始可能不是一个好主意,因为您无论如何都不会过滤它(因此它对 40M 记录执行全表扫描)。此外,正如评论中指出的那样,一个 LEFT JOIN这里不需要。 我会这样写你的查询:

SELECT o.*
FROM customers c, customer_orders o
WHERE c.id = o.Customer_Id
AND   c.Location IS NOT NULL
AND   c.Registration_Date < '2018-01-01'

这将(取决于有多少记录满足子句 Registration_Date < '2018-01-01' )过滤 customers先表,然后加入 customer_orders具有索引 customer_id 的表

另外,也许不相关,但是查询返回 40M 条记录对您来说正常吗?我的意思是,它就像整个 customer_orders table 。如果我是对的,那意味着所有订单都来自于之前“2018-01-01”

注册的客户

关于MySQL:长时间运行的 LEFT JOIN 查询性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54714493/

相关文章:

sql - 一条依赖于sql db中所有其他表记录的记录

mysql - 加入两个表并从一个表中获取一组值

mysql - 从连接表中选择 rev_parent_id=0 的第一个条目

mysql - 如何使用另一个虚拟机访问托管在虚拟机上的 MySQL 服务器?

php - 将来自适配器的 JSON 响应填充到下拉菜单中

java - 我被 spring.config、persistence.xml 和 pom 文件的不同组合所困扰

mysql - 如何选择一个表中的记录而不是另一个具有多个 PKID 的记录?

php - PHP 中的多线程/并行处理

mysql - 在MySQL中进行特殊排序,3个随机最高分,比所有随机

sql - 如何根据 Oracle 中两列值的差异合并/分组记录