TiDB 不可见索引(Invisible Index)设计与实现解析:基于 2020-03-12-invisible-index 设计文档的深度指南

发布时间:2026/9/10 2:06:11

TiDB 不可见索引(Invisible Index)设计与实现解析:基于 2020-03-12-invisible-index 设计文档的深度指南 TiDB 不可见索引Invisible Index设计与实现解析基于 2020-03-12-invisible-index 设计文档的深度指南【免费下载链接】tidbTiDB is built for agentic workloads that grow unpredictably, with ACID guarantees and native support for transactions, analytics, and vector search. No data silos. No noisy neighbors. No infrastructure ceiling.项目地址: https://gitcode.com/GitHub_Trending/ti/tidbTiDB 的不可见索引Invisible Index允许你创建或调整一个对优化器隐藏但仍持续维护的索引从而在不执行破坏性 DROP 操作的前提下安全评估删除索引对查询性能的影响。本指南以仓库中的设计文档为主体骨架结合当前 TiDB 源码实现完整讲解不可见索引的语法、行为约束、底层执行链路从ALTER INDEX到 schema 变更 Job以及优化器侧的过滤逻辑帮助你掌握这一零风险索引下线演练能力的原理与正确用法。一、不可见索引要解决什么问题索引对数据库读写性能的影响举足轻重是否存在索引、优化器是否选对了索引很大程度上决定了数据库读写的性能表现。在某些场景下我们希望评估删除某个索引对数据库读写性能的影响。过去 TiDB 的做法是借助 Index Hint 让优化器忽略指定索引虽然能达到目的但要求逐条修改所有 SQL 语句在大规模业务中并不可行见设计文档的 Background 一节。不可见索引正是为此而生它为索引增加一个可见/不可见的选项不可见的索引不会被优化器使用但依然会在 DML 操作中持续维护。对查询而言不可见索引的效果等价于通过 Index Hint 忽略该索引却无需改动任何 SQL。更关键的是删除再重建一个大表的索引代价高昂而将索引在 VISIBLE 与 INVISIBLE 之间切换是快速的原位in-place操作——这让它成为以安全方式下线索引的理想工具。二、核心语法与行为契约设计文档给出了完整的语法支持当前 TiDB 已全部实现。2.1 建索引时指定可见性INVISIBLE/VISIBLE作为索引选项index_option的一部分可在创建索引时设置也可在建表时直接设置CREATE [...] INDEX index_name [index_type] ON tbl_name (key_part,...) [index_option] index_option: {VISIBLE | INVISIBLE}具体到当前仓库建索引路径位于 pkg/ddl/index.go其中对indexOption.Visibility ast.IndexVisibilityInvisible的分支处理见pkg/ddl/index.go#L440附近将不可见标记写入索引元数据。2.2 通过 ALTER INDEX 切换可见性通过如下 DDL 可以随时将索引切换为不可见或恢复可见ALTER TABLE table_name ALTER INDEX index_name { INVISIBLE | VISIBLE };这是不可见索引最有价值的操作——它让下线演练可以随时开始、随时回滚而无需重建索引。2.3 三个必须遵守的行为约束设计文档明确了三条配套行为均已落地元数据可查不可见信息必须体现在INFORMATION_SCHEMA.STATISTICS表和SHOW INDEX输出中新增IS_VISIBLE/VISIBLE列Hint 冲突报错当不可见索引被用于索引 Hint 时需要报错主键不可隐藏主键索引不能被设置为不可见。此外还有一条容易被忽略的隐含规则来自设计文档没有显式主键的表如果存在建于 NOT NULL 列上的 UNIQUE 索引则第一个这样的唯一索引在行约束上等价于隐式主键同样不能被设置为不可见。三、从设计到实现源码级解读设计文档的 Implementation 一节列出了六项实现任务下面逐项对照当前仓库源码验证其落地情况。3.1 元数据存储IS_VISIBLE / VISIBLE 列INFORMATION_SCHEMA.STATISTICS表新增了IS_VISIBLE列其列定义TypeVarchar长度 3位于 pkg/infoschema/tables.goSHOW INDEX输出同样提供可见性信息pkg/infoschema/tables.go。同时SHOW CREATE TABLE也会展示不可见索引信息以便完整还原表结构。3.2 ALTER INDEX 的完整执行链路ALTER TABLE ... ALTER INDEX ... INVISIBLE/VISIBLE的实际执行路径如下入口pkg/ddl/executor.go 的AlterIndexVisibility将ast.IndexVisibilityInvisible映射为invisibletrue先做前置校验再构造一个类型为model.ActionAlterIndexVisibility的 DDL Job 提交给 DDL 框架校验pkg/ddl/index.go 的validateAlterIndexVisibility检查索引是否存在且处于StatePublic状态若目标状态与当前状态一致则直接跳过幂等并禁止对列式索引Columnar Index设置 INVISIBLEJob 处理onAlterIndexVisibilitypkg/ddl/index.go与setIndexVisibilitypkg/ddl/index.go在 schema 变更过程中改写索引的可见性标记该 Job 类型在 pkg/ddl/job_worker.go 中被分发处理。从源码结构看这个操作走的是标准的在线 DDLonline DDL异步 Job 机制因此不会阻塞读写这与设计文档快速的原位操作的定位一致。3.3 主键与隐式主键保护当尝试把聚簇索引clustered index主键设置为不可见时TiDB 直接拒绝pkg/ddl/create_table.go在建表/建主键路径上若constr.Option.Visibility ast.IndexVisibilityInvisible且表具有聚簇索引则返回dbterror.ErrPKIndexCantBeInvisible该错误对应 MySQL 兼容错误码ERROR 3522 (HY000): A primary key index cannot be invisible错误文案定义在 pkg/errno/errname.go。ALTER INDEX路径则通过validateAlterIndexVisibility等逻辑配合元数据校验从两个入口共同保障主键/隐式主键索引不会被隐藏。3.4 优化器如何看不见不可见索引设计文档提出不可见索引不能供优化器使用除非开关打开但对查询而言其效果等价于 Index Hint 忽略。当前实现中优化器在选择访问路径时对不可见索引做了显式过滤pkg/planner/core/planbuilder.go读取会话变量OptimizerUseInvisibleIndexes遍历表索引时若!optimizerUseInvisibleIndexes index.Invisible则直接continueFilter out invisible index, because they are not visible for optimizerpkg/planner/core/point_get_plan.go 与#L617Point Get / Batch Point Get 计划同样要求索引可见且StatePublic不可见索引不会被用于点查加速。值得注意的是与 MySQL 不同TiDB 在 SQL Hint 中显式使用不可见索引时会抛出错误设计文档 Compatibility 一节描述为 Unresolved name 错误而不是静默允许。这一点在使用 Hint 时需要格外留意。四、系统开关tidb_opt_use_invisible_indexes设计文档提出在optimizer_switch中新增use_invisible_indexes开关文档中写作use_invite_indexes为笔误用于控制 INVISIBLE 选项是否生效。TiDB 实际实现为独立系统变量变量定义于 pkg/sessionctx/vardef/tidb_vars.goTiDBOptUseInvisibleIndexes tidb_opt_use_invisible_indexes注册于 pkg/sessionctx/variable/setvar_affect.go。开关默认关闭即优化器不使用不可见索引。开启后优化器会重新考虑这些索引-- 关闭默认不可见索引不被优化器使用 set session tidb_opt_use_invisible_indexesoff; -- 开启优化器可以继续使用不可见索引 set session tidb_opt_use_invisible_indexeson;这个开关给了运维一个额外的逃生舱即使索引已设置为 INVISIBLE仍可在会话或全局层面临时恢复其参与优化用于应急或对比验证。五、为什么不用 WriteOnly 状态实现设计取舍设计文档 Rationale 一节讨论了另一种备选方案用 DDL 状态机中的WriteOnly状态来表示不可见。该方案被否决原因有三需要改动 schema 变更的核心逻辑实现复杂度高无法区分正处于 WriteOnly 迁移中的索引与被标记为不可见的索引语义互相污染处理开关是否使用不可见索引非常麻烦。当前采用索引选项 优化器过滤的方案将可见性作为独立的元数据维度与 schema 状态机解耦既保持了 DDL 框架的简单性也让可见性切换成为可随时执行、可随时回滚的轻量操作。六、兼容性与迁移这是一个全新特性与旧版本 TiDB 完全兼容不影响任何数据迁移。语法与功能基本兼容 MySQL唯一明确的差异点是当在 SQL Hint 中使用不可见索引且use_invisible_indexes false时MySQL 允许使用该不可见索引而 TiDB不允许会抛出Unresolved name错误。也就是说在把 MySQL 业务迁移到 TiDB 时如果业务 Hint 中引用了被标记为不可见的索引需要提前清理或调整相关 Hint。七、测试与验证设计文档的 Testing Plan 包括单元测试与借鉴 MySQL 不可见索引相关测试用例。当前仓库中的测试可以帮你快速验证上述所有行为pkg/planner/core/casetest/index/index_test.goTestInvisibleIndex用CREATE TABLE t1 ( a INT, KEY( a ) INVISIBLE )建表插入 10 行后先验证EXPLAIN走TableFullScan索引不可见、不被使用再set session tidb_opt_use_invisible_indexeson验证执行计划切换为IndexFullScan——这一组用例直观演示了开关对执行计划的影响pkg/ddl/db_change_test.goTestAlterIndexVisibility覆盖ALTER INDEX ... VISIBLE/INVISIBLE的 DDL 行为tests/integrationtest/r/ddl/db_integration.result 与 tests/integrationtest/r/ddl/primary_key_handle.result记录了集成测试中主键不可见报错等场景的预期输出。八、实战建议零风险的索引下线流程结合设计文档的初衷与当前实现推荐如下不可见索引演练流程切换为不可见ALTER TABLE t ALTER INDEX idx_a INVISIBLE;——索引停止被优化器使用但 DML 仍持续维护索引数据保持新鲜观察与评估在业务低峰期观察读写性能、慢查询与执行计划变化此阶段随时可以回滚回滚或确认若索引仍然必要执行ALTER TABLE t ALTER INDEX idx_a VISIBLE;立即恢复若确认无用再执行DROP INDEX idx_a ON t;——此时才执行真正破坏性的操作且由于索引始终被维护回滚重建索引仍需成本因此先 INVISIBLE 观察是唯一的低风险路径。需要注意的边界条件主键索引含隐式主键等价约束的 NOT NULL 唯一索引不能被设置为不可见列式索引同样不支持 INVISIBLESQL Hint 中显式引用不可见索引会报错而非静默忽略。总结不可见索引是 TiDB 提供的一种可逆的索引下线能力以索引元数据上的一个可见性标记为核心结合优化器访问路径过滤、独立的tidb_opt_use_invisible_indexes系统开关以及一套与 MySQL 高度兼容的语法与行为约束实现了在不动 SQL、不重建索引的前提下安全评估索引价值的目标。其底层实现ActionAlterIndexVisibilityDDL Job 优化器过滤与设计文档中的方案完全对应相关源码与测试均可在本仓库的 pkg/ddl、pkg/planner/core 与 pkg/infoschema 中查阅。【免费下载链接】tidbTiDB is built for agentic workloads that grow unpredictably, with ACID guarantees and native support for transactions, analytics, and vector search. No data silos. No noisy neighbors. No infrastructure ceiling.项目地址: https://gitcode.com/GitHub_Trending/ti/tidb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/10 2:06:11

FPGA实现AES-128加密算法:Verilog硬件设计与工程实践详解

简介:面向FPGA与硬件安全开发者的AES-128完整Verilog实现,基于Rijndael算法,覆盖密钥扩展、字节替换、行移位、列混淆等核心模块,并附带VHDL对照代码,适合用于学习对称加密算法的硬件加速、安全模块设计与芯片验证流程…

2026/9/10 2:01:11

CANN/ge图编译缓存功能

图编译缓存 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端…

2026/9/10 3:06:17

用神经网络训练游戏大局观教练:从数据到部署的完整实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/10 3:06:17

航空多光谱目标检测基准Moda:首个面向真实场景的遥感检测数据集

1. 项目概述:为什么一个“航空影像多光谱目标检测基准”值得被单独命名、发布并冠以“首个”与“具有挑战性”Moda——这个名字在遥感与计算机视觉交叉领域里,最近半年开始频繁出现在顶会论文的Related Work章节、开源项目README顶部,以及几个…

2026/9/10 3:06:17

Flutter适配OpenHarmony实战:随机任务生成器开发全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/10 3:06:17

Krea创意智能体实战:从实时生成到可控设计流程

做创意这块的,应该都感受到这两年变化有多快了。以前想验证一个视觉概念,找参考图、写需求、等设计出图,一来一回大半天就没了;现在只要有一个顺手的生成工具,很多想法当场就能可视化。Krea是我最近用得比较多的AI创意…

2026/9/10 3:06:17

OmniRoute 安全策略全解:从多层安全架构到生产加固实战

OmniRoute 安全策略全解:从多层安全架构到生产加固实战 【免费下载链接】OmniRoute Never stop coding. Free MIT AI gateway: one endpoint, 352 providers (150 free), 1200 models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, …

2026/9/9 13:11:35

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/8 7:15:15

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/10 0:00:55

目录对比去重实战:用哈希算法精准清理重复文件

我电脑里现在还有一块换了三次机的“数据墓地”硬盘,里面存着2016年以前所有旧笔记本的完整备份。平时不觉得有什么,直到前阵子想把它整理归档,发现同一个安装包、同一批照片、同一份论文草稿,在几个不同的备份目录里反复出现。更…

2026/9/10 0:00:55

Leaflet离线地图完整Demo合集:内网部署与坐标纠偏实战

简介:这是一份面向Web GIS开发者的LeafLet离线地图示例合集,帮助开发者快速掌握离线地图从搭建到交互的完整流程。压缩包共723个文件,大小14.06MB,以319个js脚本、175个html页面和29个css样式文件为主体,配合png/svg图…

2026/9/10 0:00:55

MATLAB读取Rinex 3.02观测文件:多系统GNSS数据解析实战

简介:基于MATLAB开发的Rinex3.02版观测文件(o文件)读取代码包,面向卫星定位导航方向的学习者与研究人员,用于解决新版观测文件的数据解析、历元提取与时间转换问题。压缩包共4个文件,包含两个m脚本、一个19…

2026/9/7 16:23:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/7 22:46:00

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/9 10:21:54

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码