想象你走进一座大型图书馆。墙边是一排排卡片目录柜:这套按作者姓氏排列,那套按出版社名称排列。每张卡片上都记着一个关键数字——书的唯一编号(rowid)。平时查书,管理员只能从一套目录里挑一个抽屉慢慢翻,抄下符合条件的编号,再进书库一本本取书。可现实中的请求往往很刁钻:“作者是张明、出版社是人民邮电、2020 年以后出版”。三个条件分别命中三套目录,以前的管理员只能选一套“看起来命中最少”的目录来翻,翻完还要回书库一本本核对另外两个条件,效率极低。 直到一位聪明的管理员想出了新办法:同时拉开两个抽屉,左手翻作者目录,右手翻出版社目录,把两堆编号分别抄下来,再在桌上比对、合并,最后只拿着精简后的名单去书库取书。这个“同时查多套目录、合并卡片编号”的操作,就是 MySQL 的索引合并(Index Merge)。根据合并方式不同,它分为 intersection(交集)、union(并集)、sort-union(排序合并)三种策略。这篇文章将带你彻底搞懂:什么情况下触发索引合并、内部执行流程是什么、有哪些坑,以及什么时候该干脆建一本“合订目录”(联合索引)。
对后端开发者和 DBA 来说,索引合并是读懂 EXPLAIN 中"Using index merge"的关键。理解它能让你在 SQL 调优时准确判断:该让数据库用多个单列索引,还是该建联合索引,避免凭感觉优化。
可视化演示
展示MySQL索引合并三种方式:Intersection交集合并(AND)、Union并集合并(OR)、Sort-Union排序并集的执行流程与结果集生成。
本节配有交互动效(进入视口后自动加载,约 3KB)。
Intersection交集合并 两索引同时扫描,取主键交集 AND条件触发,结果集为两索引匹配行的交集 R = Scan(IDX_A) ∩ Scan(IDX_B)
索引合并概述
想象你走进一座巨型图书馆。墙边一排排卡片柜,每套柜子只按一个规则整理卡片:这套按作者姓氏的拼音排,那套按出版社名称排。每张卡片上除了简要信息,还有一个关键数字——书的唯一编号(rowid)。平时查书,管理员从一套柜子里挑一个抽屉慢慢翻,把符合条件的编号抄下来,再进书库一本本取。这就是单列索引:一个索引只解决一种查询维度。
但现实中的请求往往很刁钻:“作者是张明、出版社是人民邮电、2020 年以后出版”。三个条件分别命中三套目录,传统的 MySQL 只能从中挑一套“看起来命中范围最小”的目录来翻,翻完拿到几十个编号,再回书库一本本核对另外两个条件是否满足。这意味着可能翻开一堆书,真正符合的却寥寥无几,大量时间被浪费。
索引合并(Index Merge)改变了这个局面:当一条 SQL 的 WHERE 条件包含多个可用单列索引的子条件时,优化器可以同时扫描多个索引,把各自得到的 rowid 集合按照一定规则合并,最终只对合并后的精简结果回表。EXPLAIN 的 Extra 列会出现"Using index merge"标记。三种合并策略由此诞生:intersection、union、sort-union。
你看,这位聪明的管理员不再迷信某个单一目录,而是让几套目录协同工作,最后把编号汇总。合并方式不止一种——有时他只需要两边都出现的编号,有时他需要所有编号。这些区别,正是接下来三节的主角。
- 第一个索引的扫描产物扫描第一个单列索引(如作者索引),得到满足其条件的 rowid 集合
- 第二个索引的扫描产物扫描第二个单列索引(如出版社索引),得到另一个 rowid 集合
- 合并操作按策略合并两个集合,常见方式有交集、并集、排序并集
Intersection交集
管理员接到请求:“找出作者是张明、同时出版社是人民邮电的书”。他左手在作者目录里抽出张明的卡片号 {7, 12, 23, 34, 56},右手在出版社目录里抽出人民邮电的卡片号 {12, 23, 45, 78}。他把两串编号摆在一起,一个一个比对,两边都出现的只有 12 和 23——于是只拿着这两个号进书库取书。这是最省力的一招:先把候选集压缩到极小。
SQL 中对应的是 AND 连接的多个等值条件。MySQL 对条件 c₁ 和 c₂ 分别做索引扫描,得到两个 rowid 集合 R_A、R_B,然后通过哈希匹配或排序归并求交集。由于交集的行数天然不超过两边各自的最小值,回表次数被压缩到最小,查询性能往往非常理想。
交集模式下还有一个额外福利:如果查询只需要索引列和主键(即覆盖索引场景),MySQL 可以省掉回表步骤,直接返回索引里的数据,进一步减少随机 IO。这是 Intersection 合并性价比最高的形态。
交集之所以高效,正是因为它“两头卡”:两边都有的编号才要,自然把厚厚一摞卡片迅速削成薄薄几页。这就好比管理员用两个抽屉互相印证,大大减少了后续取书的工作量。
- 作者索引的命中集合从 author='张明' 的索引扫描中拿到全部命中 rowid
- 出版社索引的命中集合从 publisher='人民邮电' 的索引扫描中拿到全部命中 rowid
- 逻辑与的约束rowid 必须同时属于 R_A 和 R_B 才会被保留
- 交集的规模上界交集结果不超过任意一侧的规模,回表量由此大幅缩减
Union并集
另一种请求是:“找出作者是张明,或者出版社是人民邮电的书”。管理员左手抄出作者目录的编号 {7, 12, 23, 34, 56},右手抄出出版社目录的编号 {12, 23, 45, 78}。他这次不挑“两边都出现”的,而是把两堆卡片全倒在一起,重复的 12 和 23 只留一张,然后拿着这一长串编号去书库取书。这是“集齐所有可能”的做法。
SQL 中对应 OR 连接的多个等值条件。MySQL 按各条件分别扫描索引,把得到的 rowid 集合做并集并去重。最终 Union 结果的行数可能接近两边的总和,回表次数显著大于 Intersection。如果两个条件各自命中大量数据,并集结果可能非常大,回表就成了一笔不小的开销。
Union 模式下结果集不一定按主键自然有序,因为两棵索引树的扫描顺序未必一致。若 MySQL 额外对结果做了排序或使用优先队列合并来减少随机 IO,那就演变成了更复杂的 Sort-Union 策略——这是下一节的主题。
Union 策略像一位来者不拒的图书管理员,把两堆卡片合在一起,宁可多取也不放过候选。但多取意味着书库得多跑好几趟——当回表成本升高,管理员就要开始犹豫了。
- 并集的集合表达两个索引命中集合的并集写作 R = R_A ∪ R_B
- 逻辑或的含义只要 rowid 出现在任一侧就保留,不要求两边同时满足
- 去重处理同一 rowid 在两个索引中都出现时,合并结果里只保留一份
Sort-Union排序合并
如果两堆卡片数量都很大,而且出版社那堆卡片本来就不是按编号排的,管理员直接倒在一起容易乱、去重容易漏。于是他换个做法:先把两堆卡片分别按编号从小到大整理成两摞,然后像洗牌归并一样,左手一摞右手一摞,谁小拿谁,一路走完自然得到一份有序且无重复的编号表。拿着这份有序表去书库,还能按顺序在书架间移动,少走回头路。
Sort-Union 用于各索引扫描结果不是按主键顺序返回的场景,典型代表是范围条件,例如 year > 2018 或 price < 100。MySQL 先对每路 rowid 做排序,再归并去重,从而避免 Union 模式下的大量随机回表。它多付出的代价是排序的 CPU 时间和临时空间。
既然 sort-union 多了排序这一步,它就有额外的开销。只有当“排序 + 顺序回表”的总成本低于“不排序的随机回表”时,优化器才会选择它。EXPLAIN 的 Extra 字段会显示"Using sort_union"来标识这种策略。
Sort-Union 是管理员面对“乱糟糟两堆大卡片”时的聪明妥协:先花点时间理整齐,再快速归并。这也告诉我们,索引合并不总是免费的,排序的时间成本是它最明显的代价之一。
- 对第一路结果排序把索引 A 的命中编号按主键顺序排序,得到一个有序序列
- 对第二路结果排序把索引 B 的命中编号同样排序
- 归并去重用双指针顺序比较两个有序序列,合并的同时去掉重复编号
触发条件分析
管理员虽然技艺高超,但不是每次都会用两套目录。他会先做心算:作者目录里“张明”的卡片有 80 张,出版社目录里“人民邮电”的卡片有 500 张。翻两套目录要花时间,合完还要去书库取书。如果翻一套目录再加现场抽查反而更快,那他宁可老实点,只用一套目录。
MySQL 优化器同样做成本估算:比较“用索引合并”与“用单个索引加回表过滤”与“全表扫描”三者的代价。只有当合并后的 rowid 集合显著变小,或者能避免大量回表时,优化器才会启用索引合并。如果两个条件各自的选择性都很差,合并后依然要回表大量行,优化器就会放弃这招。
有几个关键因素影响决策:第一,条件是等值还是范围,等值更利于求交集;第二,索引的区分度(cardinality),区分度高时每个索引命中行少,合并更有意义;第三,能否覆盖查询列,覆盖索引可免回表,极大提升合并性价比;第四,统计信息是否准确,过时的统计信息会让优化器做出错误选择。判断是否走了索引合并,最直接的方式是看 EXPLAIN 输出。
你看,管理员翻几套目录不是拍脑袋,而是精打细算后的选择。MySQL 优化器也是一位精明的账房先生,只有当合并策略能明显减少工作量时,它才会动用这招。
- 索引 A 的扫描成本N_A 是索引 A 中满足条件的条目数,c_idx 是单条索引扫描开销
- 索引 B 的扫描成本同理,N_B 是索引 B 的命中条目数
- 回表成本|R| 是合并后的行数,c_lookup 是每行回表随机 IO 开销,回表成本随结果规模线性增长
执行流程详解
现在,把管理员整套动作拍成一段慢镜头:第一步,他同时拉开作者柜和出版社柜的两个抽屉;第二步,一边扫卡片一边默念编号;第三步,把两串编号在桌上比对、合并;第四步,拿着最终名单去书库逐本取书。四个步骤一气呵成。
MySQL 的索引合并执行流程也分为四步。第一步,优化器解析 WHERE,识别出多个可用的单列索引及其对应条件;第二步,对每个索引执行范围扫描,得到各自的 rowid 集合;第三步,按 intersection、union 或 sort-union 的语义合并这些 rowid;第四步,按合并后的 rowid 去主表回表取完整行,若查询列全部包含在索引中则跳过这一步。
需要澄清的是,这里的“并行”指的是同一查询内多个索引扫描被 MySQL 协调地交叉推进,而不是多线程并行。多个索引的扫描结果在优化器中汇合,最终用户只看到一份结果集。理解这个流程,就能明白 EXPLAIN 输出里每一段执行信息对应哪个环节。
流程虽短,每一步都有讲究。就像管理员从抽屉到书架的每一步,都可能藏着提升效率的细节——理解了流程,你才能读懂 EXPLAIN 里每一行输出的真实含义,也才能在调优时对症下药。
- 合并 rowid 集合按策略对两批 rowid 做交集、并集或排序归并,得到合并后的候选编号
- 回表取完整行用合并后的编号回到主表,取出满足条件的完整数据行
- 覆盖索引的捷径如果索引已经包含查询要的所有列,Lookup 可以跳过,直接返回索引数据
局限性盘点
两套目录同时翻,看似万能,其实也有撑不住的时候。如果作者目录里“张明”有几千张卡片,出版社目录里的卡片更是铺满一桌,光比对就花掉半天;拿着几百个编号在书库来回绕圈,腿都要跑断。更麻烦的是,如果其中一套目录区分度极低,合出来的名单还是很大,最终效率甚至不如翻一套目录。
索引合并的局限在工程中非常明确。第一,并非所有查询都适用,子查询、函数包裹列、非直接索引条件都无法参与合并;第二,并集或排序合并的结果集很大时,回表会成为瓶颈,随机 IO 次数爆炸;第三,sort-union 显式引入排序,可能产生临时表和磁盘 IO;第四,优化器依赖统计信息,数据分布变化时可能误判,导致之前快的 SQL 突然变慢。
这里还有一个常见误区需要澄清:并非所有 AND 条件都适合 Intersection。当某个条件选择性很差时,比如 status='active' 命中 90% 的行,交集削减效果有限,MySQL 可能宁愿扫主表。而多列范围条件的组合,索引合并也帮不上忙,最终还得靠联合索引。
所以,管理员不会每次都动两套目录。当他算清“比对加取书”的总成本反而更高时,他会摇摇头说:“不如直接拿一套目录碰碰运气。” 这就是为什么 EXPLAIN 里偶尔见不到索引合并——它本来就是一种有条件的优化,不是银弹。
- 两次索引扫描的基础成本无论哪种合并方式,都要先付出两棵索引树的扫描代价
- 排序开销只要涉及 sort-union,排序的 CPU 与临时空间成本随结果规模近似 O(m log m) 增长
- 随机回表代价按无序 rowid 回表时,随机 IO 成本随行数线性上升,结果越大越失控
SQL调优对比
当“作者 + 出版社”的组合查询一天出现几百次,管理员终于下定决心:专门做一本“作者 × 出版社”合订目录。每一页按作者排,页内再按出版社排,一翻就到目标卡片,一次抽屉搞定,不用再比对两堆卡片。这是图书馆的联合索引。
联合索引将多个列放进同一棵 B+ 树,按列优先级排序。对于 AND 组合条件,联合索引一次范围扫描即可得到精确范围,通常比索引合并的两次扫描加合并更高效。尤其当结果集较大、需要排序或需要覆盖更多列时,联合索引的优势更加明显。同时要注意最左前缀原则:列顺序很重要,“作者 + 出版社”与“出版社 + 作者”是两种不同的目录。
那什么时候保留索引合并呢?当两个独立条件各自高频出现、组合查询低频出现时,保留单列索引更灵活;当单列索引已经存在、不想额外维护时;当查询列恰好能被索引覆盖时。反过来,当组合条件是固定高频查询、EXPLAIN 显示 Using index merge 且回表次数巨大、或者查询需要排序分组时,建联合索引是更好的选择。
管理员最终明白了:目录不是越多越好,而是“用得上的合订、用不上的单列”。合订目录和多目录合并各有各的主场,理解它们的分工,你才能在真实 SQL 调优中做出理性选择,而不是盲目追求某一种方案。
- 联合索引的成本联合索引一次有序扫描加回表的代价,取决于组合条件的命中范围
- 索引合并的成本两次扫描、排序/归并再加上回表,额外付出合并与排序的代价
- 成本比较当 N_A 与 N_B 之和较大或需要排序时,联合索引的一方明显更划算
AI 应用场景
电商订单检索中的 Intersection 优化
阶段:在线业务数据查询与特征检索
解决的问题:订单表上 user_id 和 status 各有单列索引,旧代码习惯写 WHERE user_id=? AND status='paid'。MySQL 有时走 index merge,但当 status 区分度低时反而慢,SQL 响应时间波动大。
具体案例:某电商平台订单中心按用户加支付状态批量拉取订单,慢查询日志显示 rows_examined 高达数万。DBA 通过 EXPLAIN 定位到 Using index merge,为高频组合建立联合索引 (user_id, status),P99 延迟从 800ms 降到 60ms。
内容平台多标签 OR 检索
阶段:推荐系统在线推理阶段的数据召回
解决的问题:推荐服务需要召回“近 7 天高互动”或“人工精选”两类内容,两列各有单列索引,OR 条件触发 sort-union,但排序和回表导致延迟偏高。
具体案例:某资讯 App 的标签筛选页,用户勾选多个标签时 SQL 产生多个 OR 条件。通过 EXPLAIN 定位到 Using sort_union,为最高频的标签组合建立联合索引后,召回接口平均延迟下降 45%。
数据分析看板的多条件筛选
阶段:BI 数据报表与多维分析
解决的问题:数据看板按日期、地区、渠道多维过滤,多个单列索引导致优化器频繁选择 index merge,但统计信息变化时执行计划不稳定,接口时快时慢。
具体案例:某 SaaS 团队的数据看板接口,同样的筛选条件在不同时间响应差异巨大。后来统一为固定组合列建立联合索引,查询计划保持稳定,接口耗时的标准差下降 70%。
Python 演示
# -*- coding: utf-8 -*-"""模拟 MySQL 索引合并的三种策略: intersection / union / sort-union""" def build_index(rows, key_func): """根据 key 函数为数据行构建索引: key -> [rowid 列表]""" index = {} for rowid, row in enumerate(rows): key = key_func(row) index.setdefault(key, []).append(rowid) return index def index_intersection(left_rowids, right_rowids): """Intersection 策略: 对两个 rowid 列表求交集""" right_set = set(right_rowids) return [r for r in left_rowids if r in right_set] def index_union(left_rowids, right_rowids): """Union 策略: 对两个 rowid 列表求并集""" return list(set(left_rowids) | set(right_rowids)) def index_sort_union(left_rowids, right_rowids): """Sort-Union 策略: 排序后合并去重""" return sorted(set(left_rowids) | set(right_rowids)) def main(): # 生成模拟数据行: (作者编号, 出版社编号, 年份) rows = [ (author, publisher, year) for author in range(1, 6) for publisher in range(1, 4) for year in range(2015, 2021) ] idx_author = build_index(rows, lambda row: row[0]) idx_year = build_index(rows, lambda row: row[2]) author_id, target_year = 3, 2019 rowids_a = idx_author[author_id] rowids_b = idx_year[target_year] inter = index_intersection(rowids_a, rowids_b) union = index_union(rowids_a, rowids_b) sort_union = index_sort_union(rowids_a, rowids_b) print("author=3 -> %s" % rowids_a) print("year=2019 -> %s" % rowids_b) print("intersection: %s" % inter) print("union: %s" % union) print("sort-union: %s" % sort_union) if __name__ == "__main__": main()
index.setdefault(key, []).append(rowid)如果 key 不存在就初始化空列表再追加,一行代码完成索引构建right_set = set(right_rowids)转成集合,让后续“是否在另一侧”的判断从 O(n) 降到 O(1)[r for r in left_rowids if r in right_set]逐个判断并保留两侧都出现的 rowid,实现交集set(left_rowids) | set(right_rowids)集合求并集,自动去重sorted(...)这是 Sort-Union 比 Union 多出的关键一步:排序后再输出
常见误区
误区我建了好几个单列索引,MySQL 应该每次查询都同时用它们。结果 EXPLAIN 却显示只用了其中一个索引,是不是 MySQL 出 bug 了?
正解索引合并只是优化器的候选策略之一,不是默认行为。只有当合并后的成本低于单个索引回表或全表扫描时,优化器才会选它。如果某个条件命中行数很多,合并反而更慢,优化器自然会放弃。就像管理员不是每次都翻两套目录,只有当两套目录合查更省时才会动手。
为何常见:我们把“有多个索引”等同于“会被同时使用”,忽略了优化器基于成本做权衡的本质。
误区索引听起来就很高效,走索引合并总比把整张表扫一遍强吧?那我给所有列都加上单列索引,查询就永远快了。
正解如果两个索引的区分度都很低,比如 status 字段只有 3 种取值,各自命中几十万行,合并后还是要回表几十万次,随机 IO 远高于顺序读的全表扫描。此时优化器会果断选择全表扫描。索引合并不是银弹,它只是成本模型中的一个选项。
为何常见:直觉上“用了索引就快”,但忽略了随机 IO 和顺序 IO 之间的巨大差异。
误区既然一条 SQL 可以用多个索引合并,那就不需要建联合索引了,还能省下不少存储空间。以后遇到慢查询,加单列索引就够了。
正解联合索引一次有序扫描即可覆盖多个条件,还支持覆盖索引避免回表。对高频组合查询,联合索引通常更高效、更稳定。索引合并更像“救火队”,能应急但没有正规军的结构化优势。合订目录虽然多占一点空间,但查起来确实更快。
为何常见:看到索引合并的“聪明”,忽略了两者在代价结构和适用场景上的根本差异。
误区索引的叶子节点已经包含主键,那通过索引合并应该就能拿到所有数据了吧?是不是可以不用回表了?
正解二级索引只保存索引列加主键,不包含完整行数据。如果查询还需要其他列,比如书名、价格、库存,就必须回表取完整行。只有查询列全部包含在索引中,也就是覆盖索引时,Intersection 才能免回表。卡片目录记的是编号和索引信息,要拿书的完整内容还是得去书库。
为何常见:混淆了“索引包含主键”与“索引包含完整行数据”这两个概念。
面试题
Q1. 什么是 MySQL 的索引合并?
- A.一条 SQL 同时使用多个单列索引并合并结果集← 正确答案
- B.多个 SQL 共享同一个查询缓存
- C.多个索引合并成一个联合索引
- D.数据库自动删除冗余索引来节省空间
答案:A。索引合并在一条查询中同时利用多个单列索引,各自扫描后合并 rowid 集合,对应 EXPLAIN 中的 Using index merge。B 是查询缓存,C 是索引合并的反向操作,D 与合并无关。
Q2. 下面哪种 SQL 场景最可能触发 Intersection 合并?
- A.WHERE a=1 AND b=2 且 a、b 各有单列索引← 正确答案
- B.WHERE a=1 OR b=2 且 a、b 各有单列索引
- C.WHERE a IN (1,2) 且 a 列有单列索引
- D.WHERE a=1 ORDER BY b 且 b 列无索引
答案:A。Intersection 对应 AND 连接的等值条件,取两边 rowid 的交集。OR 应走 Union,IN 只命中一个索引,ORDER BY 无索引不参与。就像管理员要找“既在作者目录又在出版社目录”的编号。
Q3. Union 与 Sort-Union 的主要区别是什么?
- A.前者只支持等值条件,后者支持范围条件
- B.前者合并两个索引,后者合并多个索引
- C.后者多一步按 rowid 排序再归并去重← 正确答案
- D.两者名称不同但行为完全一致
答案:C。Sort-Union 在 Union 基础上增加了“先排序再归并”的步骤,目的是把无序的 rowid 变为有序,减少回表随机 IO。A 不准确,B 中数量不是区别,D 完全错误。
Q4. 为什么 OR 条件走索引合并可能比全表扫描还慢?
- A.因为 OR 条件本身无法使用任何索引
- B.MySQL 不允许 OR 与索引合并同时使用
- C.合并后回表的随机 IO 次数可能非常大← 正确答案
- D.索引合并只支持等值查询条件
答案:C。OR 合并的结果集接近两边命中行数之和,若两个条件命中大量行,合并后回表会产生海量随机 IO。顺序读的全表扫描反而更快。A、B、D 都与 MySQL 实际行为不符。
Q5. EXPLAIN 的 Extra 字段显示什么表示走了索引合并?
- A.Using filesort
- B.Using index merge← 正确答案
- C.Using temporary
- D.Using where
答案:B。Using index merge 是索引合并的标志。Using filesort 表示排序,Using temporary 表示临时表,Using where 只是在存储引擎层做了条件过滤,三者都不是索引合并。
Q6. 索引合并的三种策略包括哪些?
- A.交集合并策略和并集合并策略← 正确答案
- B.排序合并策略即 Sort-Union← 正确答案
- C.全表合并策略完整扫描全表
- D.哈希连接策略驱动合并
答案:AB。MySQL 索引合并只有 intersection、union、sort-union 三种。C 是全表扫描,D 是连接算法,均不属于索引合并。管理员翻两套目录只有比对、合堆、排序合堆三种做法。
Q7. 联合索引通常比索引合并高效,最本质的原因是什么?
- A.索引合并需要多次全表扫描
- B.联合索引不占用额外磁盘空间
- C.索引合并只能在内存中完成
- D.联合索引单次有序扫描且可覆盖多列← 正确答案
答案:D。联合索引把多列放进一棵 B+ 树,一次有序扫描即可完成过滤,还能通过覆盖索引避免回表。A、B、C 描述均不准确:索引合并扫的是索引不是全表,联合索引占用空间,索引合并也可以在内存完成。
Q8. 关于索引合并的触发条件,下列说法正确的有?
- A.查询条件命中多个单列索引← 正确答案
- B.优化器估算合并成本更低← 正确答案
- C.只要建了联合索引就必然触发
- D.条件可以是 AND 或 OR 组合形式← 正确答案
答案:ABD。索引合需要多个单列索引被同时命中,且优化器认为合并成本更低。AND 对应 Intersection,OR 对应 Union/Sort-Union。建了联合索引并不能保证触发索引合并,联合索引是另一套机制。
Q9. 什么情况下 Intersection 合并的性价比最高?
- A.两个索引命中行数都非常多
- B.查询列被索引覆盖无需回表← 正确答案
- C.查询只包含一个字段条件
- D.目标表本身是临时表
答案:B。当查询列全部包含在索引中时,Intersection 可以直接返回索引数据,省去回表步骤,性价比最高。A 中命中行数多会导致交集也大;C 无法触发合并;D 与合并策略无关。
Q10. 关于索引合并局限性的说法,正确的有哪些?
- A.子查询里的条件无法参与索引合并← 正确答案
- B.Sort-Union 可能产生排序临时文件← 正确答案
- C.优化器不会因统计信息错误误判
- D.结果集很大时回表成本成为瓶颈← 正确答案
答案:ABD。子查询中的条件难以直接映射到单列索引合并;sort-union 的排序可能落盘产生临时文件;结果集大时随机回表成本失控。C 错误,因为优化器依赖统计信息,统计信息过期完全可能误判执行计划。