mysql - MySQL:长时间运行的 LEFT JOIN 查询性能
问题描述
MySQL 数据库包含两个表:customer和custmomer_orders
客户表包含 8000 万个条目并包含 80 个字段。其中一些我感兴趣:
- 标识 (PK, int(10))
- 位置(varchar 255,可为空)。
- Registration_Date(日期时间,可为空)。索引。
customer_orders表包含 4000 万个条目,并且仅包含 3 个字段:
- 标识 (PK, int(10))
- Customer_Id (int(10), FK 到客户表)
- 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 的 RAM,28GB 分配给 MySQL。MySQL 版本:5.6.39。
MySQL 在具有这么多记录的表上执行这么长时间的查询是否正常?我怎样才能提高性能?
更新:
customer_orders 表不包含我们想要存储的任何重要数据。这是最近 10 天内下订单的某种复制表。每天我们都会运行一个存储过程,它会删除事务范围内超过 10 天的订单。
有一段时间,这个存储过程由于没有优化查询而超时,订单数量每天都在增长。以前的查询还包含 COUNT 方法,我想它超过了超时。
尽管如此,让我感到惊讶的是,MySQL 最多需要 15 分钟才能在附加条件下获取 40m 条记录。
解决方案
我认为这很正常。explain
如果您分享该查询的返回值,将会很有帮助。
为了优化查询,从 customer_orders 开始可能不是一个好主意,因为无论如何您都没有过滤它(因此它对 40M 记录执行全表扫描)。此外,正如评论中所指出的, LEFT JOIN
这里不需要 a 。我会这样写你的查询:
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
桌子。如果我是对的,这意味着所有订单都来自在'2018-01-01'之前注册的客户
推荐阅读
- swift - 如何将文件移动到 iOS 13 中的文档目录中?
- finance - 查找财务报表
- git - 将一半完成的工作推到回购是一种不好的做法吗?
- android - ListView 和 R 字符串目录
- memory-leaks - Directx 11 CreateVertexShader 内存泄漏
- css - 如何使用 CSS 覆盖各种浏览器的打印首选项?
- oracle - 尝试合并时合并条件在 oracle 中不起作用
- android - 如何在 android Textview 上使用斜线制作可点击的 url 链接
- objective-c - 重构用目标 C 编写的应用程序?
- mysql - 从 Azure sql 数据库导入存储库时出错