[英]MySQL WHERE EXISTS subquery performance between 5.7 and 8.0
[英]MySQL exists subquery performs significantly worse in 8.0 than 5.7
我希望将我的 MySQL 数据库从 5.7.33 升级到 8.0.28。 我将它与一个 Laravel 应用程序一起使用,该应用程序使用whereHas
方法生成查询,该方法使用存在子查询。 但是,我注意到两个版本之间的性能大幅下降 - 从约 5 毫秒到 4 秒。
以下是查询:
select * from `categories` where exists (select * from `jobs` inner join `category_job` on `jobs`.`id` = `category_job`.`job_id` where `categories`.`id` = `category_job`.`category_id`) order by `name` asc
有趣的是,如果我完全删除存在的子查询,查询又会恢复到合理的速度——大约 5 毫秒。
select * from `categories` order by `name` asc
我试图理解的是为什么两个版本之间的性能变化如此之大 - 如果我的 SQL 中存在可以改进的错误(或者可能在框架中进行更改以避免问题) - 或者这只是一个我将不得不忍受的 MySQL 中的性能回归。
我知道第一个查询的工作量更大,并且使用 exists 子查询会变慢,但我不明白升级 MySQL 是如何产生效果的。
当我使用 EXPLAINS 运行查询时,我也会在 5.7 和 8.0 之间得到不同的结果(还要注意数据库具有相同的索引):
5.7:
ID | 选择类型 | 桌子 | 分区 | 类型 | 可能的键 | 钥匙 | key_len | 参考 | 行 | 过滤 | 额外的 |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 基本的 | 类别 | 全部 | 27 | 100.00 | 使用哪里; 使用文件排序 | |||||
2 | 依赖子查询 | 类别工作 | 参考 | category_job_category_id_index,category_job_job_id_index | category_job_category_id_index | 8 | Jobsnearme.categories.id | 35253 | 100.00 | ||
2 | 依赖子查询 | 工作 | eq_ref | 基本的 | 基本的 | 8 | jobsnearme.category_job.job_id | 1 | 100.00 | 使用索引 |
8.0:
ID | 选择类型 | 桌子 | 分区 | 类型 | 可能的键 | 钥匙 | key_len | 参考 | 行 | 过滤 | 额外的 |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 简单的 | 类别 | 无效的 | 全部 | 基本的 | 无效的 | 无效的 | 无效的 | 30 | 100.00 | 使用文件排序 |
1 | 简单的 | 无效的 | eq_ref | <auto_distinct_key> | <auto_distinct_key> | 8 | Jobsnearme.categories.id | 1 | 100.00 | 无效的 | |
2 | 物化 | 工作 | 无效的 | 指数 | 基本的 | jobs_company_id_index | 9 | 无效的 | 718220 | 100.00 | 使用索引 |
2 | 物化 | 类别工作 | 无效的 | 参考 | category_job_category_id_index,category_job_job_id_index | category_job_job_id_index | 8 | jobsnearme.jobs.id | 1 | 100.00 | 无效的 |
这是来自 8.0 的SHOW CREATE TABLE category_job
:
CREATE TABLE `category_job` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`category_id` bigint unsigned NOT NULL,
`job_id` bigint unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `category_job_category_id_index` (`category_id`),
KEY `category_job_job_id_index` (`job_id`),
CONSTRAINT `category_job_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`),
CONSTRAINT `category_job_job_id_foreign` FOREIGN KEY (`job_id`) REFERENCES `jobs` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1070585 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
多对多表模式中的常见低效问题。
这会更快:
CREATE TABLE `category_job` (
`category_id` bigint unsigned NOT NULL,
`job_id` bigint unsigned NOT NULL,
PRIMARY KEY (category_id, job_id),
KEY (job_id, category_id)
) ENGINE=InnoDB
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.