You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL关联查询中JSON数组索引未生效的差异原因分析

解答

核心差异在于连接条件中d.id是常量还是动态变量,这直接决定了MySQL能否利用directory表的idx_datasets索引:

1. 第一个查询(where d.id = 111):常量驱动的连接

当你用d.id = 111过滤时,MySQL对dataset表的处理是常量查找(执行计划里type: const)——通过主键索引直接定位到唯一一行,拿到d.id = 111这个固定值。

此时连接条件JSON_CONTAINS(dir.datasets, cast(d.id as json))等价于JSON_CONTAINS(dir.datasets, '111'),111是一个明确的常量。MySQL可以将这个条件转化为:查找dir.datasets数组中包含111的行,而你创建的idx_datasets是基于cast(datasets as unsigned array)的函数索引,正好支持这种数组包含查询,所以directory表可以用range类型的索引扫描快速定位符合条件的行。

2. 第二、三个查询(where d.name like '111'/d.name = '111'):变量驱动的连接

当过滤条件是d.name时,MySQL先通过idx_name索引找到符合条件的dataset行(执行计划里d表的type是range或ref),但这些行的d.id是动态变量——即使这里只返回1行,MySQL依然将其视为不确定的变量。

对于directory表的连接条件JSON_CONTAINS(dir.datasets, cast(d.id as json)),MySQL无法将这个变量参数与idx_datasets索引结合使用:因为idx_datasets是针对dir.datasets数组构建的索引,MySQL没有办法高效地用一个动态变化的d.id值去匹配数组索引中的元素。因此,MySQL只能对directory表做全表扫描(type: ALL),然后通过哈希连接(hash join)逐一检查每个dir.datasets是否包含当前d.id的值。

简单总结:只有当连接条件中的查找值是已知常量时,MySQL才能利用directory表的数组索引;如果是来自关联表的动态变量,就只能走全表扫描+连接缓冲区的方式。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 16:08:16