gpt4 book ai didi

mysql - MySQL 是否优化相关表上的选定聚合以避免 N+1?

转载 作者:行者123 更新时间:2023-11-29 00:10:03 25 4
gpt4 key购买 nike

这个查询在 MySQL 中是最优的吗?我的意思是:执行的查询数量是恒定的吗?

或者它是否属于 N+1 问题?在官方 MySQL 文档中没有找到关于优化的详细信息。

SELECT t.*, (SELECT COUNT(1) from related_table rt where rt.t_id = t.id)
FROM table t

在天真的看法中,有一个查询和 N 个查询,所以它会落入 N+1 问题。

MySQL 5.5+ 是否会自动+内部改进此查询以进行恒定数量的查询?也许在内部将其转换为类似的东西:

SELECT t.*, COUNT(rt.id)
FROM table t LEFT OUTER JOIN related_table rt
GROUP BY t.id

我的意思是:我知道如何手动改进它,但我问这个是因为:

  1. 也许通过库对具有(某种程度上不完整的恕我直言)ORM 的框架进行分配。
  2. 好奇心。在官方 MySQL 文档中找不到太多文档。

最佳答案

不,选择列表中的相关子查询没有被 MySQL 优化掉。

您可以通过使用 EXPLAIN 获取优化计划报告来确认这一点。下面是一个使用测试数据库的类似查询:

mysql> explain select *, (SELECT COUNT(*) FROM cast_info where cast_info.role_id = role_type.id) AS c 
from role_type\G
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: role_type
partitions: NULL
type: index
possible_keys: NULL
key: role
key_len: 98
ref: NULL
rows: 12
filtered: 100.00
Extra: Using index
*************************** 2. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: cast_info
partitions: NULL
type: ref
possible_keys: cr
key: cr
key_len: 4
ref: imdb.role_type.id
rows: 2534411
filtered: 100.00
Extra: Using index

DEPENDENT SUBQUERY的select类型意味着子查询会被执行多次,很可能外层查询的每一行执行一次。

与手动优化查询的 EXPLAIN 比较:

mysql> explain select r.*, COUNT(c.id) AS c from role_type AS r  left outer join cast_info as c on r.id = c.role_id group by r.id\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: r
partitions: NULL
type: index
possible_keys: PRIMARY,role
key: PRIMARY
key_len: 4
ref: NULL
rows: 12
filtered: 100.00
Extra: NULL
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: c
partitions: NULL
type: ref
possible_keys: cr
key: cr
key_len: 4
ref: imdb.r.id
rows: 2534411
filtered: 100.00
Extra: Using index

这表明对第二个表的访问只是一个简单的按引用连接。

您还可以使用 MySQL query profiler 进行测试.这是第二个查询,它使用连接:

+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000167 |
| checking permissions | 0.000015 |
| checking permissions | 0.000016 |
| Opening tables | 0.000050 |
| init | 0.000059 |
| System lock | 0.000044 |
| optimizing | 0.000011 |
| statistics | 0.000151 |
| preparing | 0.000099 |
| Sorting result | 0.000019 |
| executing | 0.000010 |
| Sending data | 9.700879 |
| end | 0.000024 |
| query end | 0.000022 |
| closing tables | 0.000017 |
| freeing items | 0.000243 |
| cleaning up | 0.000056 |
+----------------------+----------+

这是带有依赖子查询的那个:

+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000152 |
| checking permissions | 0.000014 |
| checking permissions | 0.000013 |
| Opening tables | 0.000050 |
| init | 0.000067 |
| System lock | 0.000042 |
| optimizing | 0.000010 |
| statistics | 0.000367 |
| preparing | 0.000033 |
| optimizing | 0.000015 |
| statistics | 0.000032 |
| preparing | 0.000020 |
| executing | 0.000010 |
| Sending data | 0.000191 |
| executing | 0.000010 |
| Sending data | 4.103899 |
| executing | 0.000018 |
| Sending data | 2.413570 |
| executing | 0.000018 |
| Sending data | 0.043924 |
| executing | 0.000022 |
| Sending data | 0.037834 |
| executing | 0.000020 |
| Sending data | 0.014127 |
| executing | 0.000021 |
| Sending data | 0.089977 |
| executing | 0.000023 |
| Sending data | 0.045968 |
| executing | 0.000024 |
| Sending data | 0.000044 |
| executing | 0.000005 |
| Sending data | 0.190935 |
| executing | 0.000034 |
| Sending data | 1.046394 |
| executing | 0.000018 |
| Sending data | 0.017567 |
| executing | 0.000021 |
| Sending data | 0.882959 |
| end | 0.000046 |
| query end | 0.000023 |
| closing tables | 0.000018 |
| freeing items | 0.000248 |
| cleaning up | 0.000025 |
+----------------------+----------+

可以看到子查询导致了多次执行。在我的例子中,我在 role_type 表中只有几行,但如果你有成百上千行,子查询执行的次数可能会变得很长,以至于分析器会截断该报告。

关于mysql - MySQL 是否优化相关表上的选定聚合以避免 N+1?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25613676/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com