0
1
2
1
博客/.../

TiDB 索引详解:索引概念、分类、用途与最佳实践

 北南南北  发表于  2026-03-13

1. 引言

TiDB 是一款国产原生的分布式数据库,兼容 MySQL 协议,具备水平扩展、高可用和强一致性等特性。在分布式数据库环境中,索引的设计和使用对于查询性能至关重要。TiDB 的索引机制在继承传统关系型数据库索引概念的基础上,结合其底层 Key-Value 存储(TiKV)的分布式特性,形成了一套独特的实现。本文将深入探讨 TiDB 索引的核心概念、主要分类、实际用途、典型使用场景,并通过示例进行说明,最后提供一些在分布式环境下的最佳实践。

2. TiDB 索引的核心概念与实现原理

在 TiDB 中,所有数据(包括表数据和索引数据)最终都以 Key-Value 对的形式存储在 TiKV 集群中。理解这一点是理解 TiDB 索引工作原理的关键。

2.1 Key-Value 映射

TiDB 将关系型数据模型映射到底层的 Key-Value 存储:

  • 行数据:每行数据被编码为一个 Key-Value 对。Key 的结构通常是 tablePrefix{tableID}_recordPrefixSep{rowID},Value 存储了该行的所有列数据。rowID 是每行的唯一标识符,对于没有显式主键的表,TiDB 会自动生成一个隐式的 _tidb_rowid
  • 索引数据:每个索引也被编码为 Key-Value 对。Key 的结构是 tablePrefix{tableID}_indexPrefixSep{indexID}_indexedColumnsValue,Value 存储了对应的 rowID 。这意味着索引存储的是索引列的值与对应数据行 rowID 的映射关系。

2.2 分布式特性

由于 TiKV 是一个分布式 Key-Value 存储,索引数据也会根据 Key 的范围被自动打散并存储在不同的 TiKV Region 中。当 TiDB 接收到查询请求时,其优化器会根据查询条件选择合适的索引,并将查询 Key 的范围下推到对应的 TiKV 节点进行并行处理,从而实现分布式查询优化 。

3. TiDB 索引的分类

TiDB 的索引可以从多个维度进行分类,包括物理存储方式、功能特性以及特殊类型。

3.1 聚簇索引与非聚簇索引

TiDB 从 v 5.0 版本开始支持聚簇索引(Clustered Index),这改变了数据行的物理存储方式 。

  • 聚簇索引:当表定义了主键且启用了聚簇索引特性时,数据行会按照主键的顺序物理存储。此时,行数据的 Key 直接包含主键值,即 tablePrefix{tableID}_recordPrefixSep{primaryKey}。通过聚簇索引查询主键时,可以直接定位到数据行,减少了一次网络交互和“回表”操作,尤其适用于主键查询频繁和主键范围扫描的场景。
  • 非聚簇索引:这是 TiDB 默认的索引方式(在 v 5.0 之前所有表都是非聚簇的,或者当表没有主键时)。数据行的 Key 使用系统自动生成的 _tidb_rowid。非聚簇索引的叶子节点存储的是索引列的值和对应的 rowID。当通过非聚簇索引查询主键以外的列时,需要先通过索引找到 rowID,再根据 rowID 去 TiKV 查找实际的数据行,这个过程称为“回表” 。

3.2 二级索引 (Secondary Index)

二级索引是在非主键列上创建的索引,用于加速基于这些列的查询。根据其约束条件,二级索引又可分为:

  • 唯一索引 (Unique Index):确保索引列的值在表中是唯一的,但允许为 NULL(除非列定义为 NOT NULL)。
  • 普通索引 (Normal Index):最基本的索引类型,不强制要求列值唯一,允许重复值和 NULL 值。

3.3 特殊索引类型

TiDB 还支持一些特殊类型的索引,以应对更复杂的查询需求:

  • 联合索引 (Composite Index):在多个列上创建的索引,例如 INDEX idx_name_age (name, age)。联合索引遵循最左前缀原则,即只有查询条件中包含了索引的最左侧列,索引才可能被使用。例如,WHERE name = 'Alice' 可以使用 idx_name_age,而 WHERE age = 20 则不能 。
  • 表达式索引 (Expression Index):TiDB v 6.5+ 支持,允许对表达式的结果创建索引,而不是直接对列创建索引。例如,CREATE INDEX idx_lower_name ON users (LOWER(name)),可以加速 WHERE LOWER(name) = 'alice' 这样的查询 。
  • 多值索引 (Multi-valued Index):TiDB v 7.1+ 支持,主要用于 JSON 类型数据。它可以对 JSON 数组中的每个元素创建索引,从而高效查询 JSON 字段中的特定值。多值索引通常与倒排索引结合使用 。
  • 倒排索引 (Inverted Index):TiDB v 7.1+ 支持,是一种特殊的索引结构,主要用于全文搜索和多值索引。它将文档中的每个词或 JSON 数组中的每个元素映射到包含它们的文档 ID 列表,从而实现快速查找 。
  • 全局索引 (Global Index):针对分区表,全局索引消除了唯一键必须包含所有分区列的限制,极大地提升了索引设计的灵活性 。

4. 索引的用途与使用场景

TiDB 索引的主要用途与传统数据库类似,旨在提升查询性能和数据完整性,但在分布式环境下,其优化效果更为显著。

4.1 主要用途

  • 加速数据检索:通过索引,TiDB 可以避免全表扫描,快速定位到所需数据,尤其在处理海量数据时,性能提升巨大 。
  • 保证数据唯一性:唯一索引和主键索引确保了特定列的数据不重复,维护了数据的一致性和完整性。
  • 优化排序和分组:当查询涉及 ORDER BYGROUP BY 操作时,如果相关列上存在索引,TiDB 可以直接利用索引的有序性,减少额外的排序计算。
  • 加速表连接:在 JOIN 操作中,如果连接条件列上存在索引,可以显著提高连接效率。

4.2 典型使用场景

索引类型 典型使用场景 示例 SQL 备注
聚簇索引 主键等值查询、主键范围查询 SELECT * FROM users WHERE id = 100; SELECT * FROM orders WHERE order_id BETWEEN 1000 AND 2000; 减少回表,适用于主键查询频繁的业务
二级索引 非主键列的等值或范围查询 SELECT * FROM products WHERE category = 'Electronics'; SELECT * FROM logs WHERE event_time > '2023-01-01'; 最常见的索引类型
联合索引 多条件组合查询,遵循最左前缀原则 SELECT * FROM users WHERE last_name = 'Smith' AND first_name = 'John'; 需注意列的顺序,将选择性高的列放前面
表达式索引 对函数或表达式结果进行查询 SELECT * FROM articles WHERE LOWER(title) LIKE 'tidb%'; 避免全表扫描,提升函数查询性能
多值索引 JSON 数组中元素的查询 SELECT * FROM products WHERE JSON_CONTAINS(tags, '"new_arrival"'); 适用于半结构化数据查询

5. TiDB 索引的最佳实践

在 TiDB 分布式环境中,索引的优化需要考虑更多因素,以避免潜在的性能问题。

  • 选择合适的 PRIMARY KEY

    • 对于高并发写入场景,避免使用自增整数作为主键,因为这可能导致单个 TiKV Region 的写入热点。建议使用 AUTO_RANDOM 或 UUID 等散列性较好的主键 。
    • 如果业务查询主要通过主键进行,且主键是自增的,可以考虑使用聚簇索引来减少回表开销。
  • 避免热点问题:除了主键,二级索引也可能产生热点。例如,如果一个二级索引的列值分布不均匀,大量查询集中在少数几个值上,也可能导致热点。可以通过加盐(Salting)或反转索引等方式来缓解 。

  • 覆盖索引 (Covering Index):尽量让查询语句中 SELECT 的所有列和 WHEREORDER BYGROUP BY 中的所有列都包含在同一个索引中。这样,TiDB 只需要扫描索引而无需“回表”查询数据行,从而显著提高查询效率 。

  • 前缀索引 (Prefix Index):对于较长的字符串列,可以创建前缀索引来节省存储空间并提高索引效率。例如,CREATE INDEX idx_email_prefix ON users (email(10))。但需要注意,前缀索引可能无法用于覆盖索引和 ORDER BY 操作 。

  • 合理使用联合索引:根据查询模式,将经常一起查询的列创建为联合索引,并遵循最左前缀原则。例如,如果 WHERE a = ? AND b = ? 是常见查询,则 INDEX (a, b) 优于 INDEX (b, a)

  • 定期收集统计信息:TiDB 的优化器依赖于准确的统计信息来选择最佳的执行计划。定期执行 ANALYZE TABLE 命令可以帮助优化器做出更明智的索引选择 。

  • 监控与调优:使用 TiDB Dashboard、EXPLAINEXPLAIN ANALYZE 等工具来分析慢查询,识别未被使用的索引或索引使用不当的情况,并进行相应的调整 。

  • 避免过度索引:过多的索引会增加写入开销,并占用额外的存储空间。只为真正能提升查询性能的列创建索引。

6. 结论

TiDB 的索引机制是其分布式架构中不可或缺的一部分,它在兼容 MySQL 语法的同时,通过底层 Key-Value 存储和分布式查询优化,为海量数据场景提供了高效的数据检索能力。深入理解 TiDB 索引的分类、实现原理、用途和最佳实践,对于构建高性能、高可用的分布式应用至关重要。通过精心设计和持续优化索引,可以充分发挥 TiDB 的强大潜力,满足不断增长的业务需求。

0
1
2
1

版权声明:本文为 TiDB 社区用户原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接和本声明。

评论
暂无评论