繁体   English   中英

MySQL 存在子查询在 8.0 中的性能明显比 5.7 差

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM