Skip to content

TDSQL 索引管理

索引类型与特点

1. 主键索引

  • 唯一标识表中的每一行记录
  • 自动创建,一个表只能有一个主键
  • 存储引擎会自动为主键创建B+树索引
  • 主键值不能为空

2. 唯一索引

  • 确保索引列的值唯一
  • 允许有空值(但最多一个)
  • 适合用作业务唯一标识

3. 普通索引

  • 最基本的索引类型
  • 加速数据查询
  • 允许重复值和空值

4. 复合索引

  • 基于多个列创建的索引
  • 遵循最左前缀原则
  • 适合多列查询场景

5. 全文索引

  • 用于全文搜索
  • 支持自然语言搜索和布尔搜索
  • 适合大文本字段查询

6. 空间索引

  • 用于地理空间数据类型
  • 支持空间关系查询
  • 适合地图应用等场景

索引设计原则

1. 选择合适的索引列

  • 经常出现在WHERE子句中的列
  • 用于JOIN操作的列
  • 用于ORDER BY和GROUP BY的列
  • 高选择性的列(唯一值比例高)

2. 复合索引设计

  • 将最常用的列放在前面
  • 遵循最左前缀原则
  • 避免创建过多复合索引
  • 考虑索引覆盖查询

3. 避免过度索引

  • 索引会占用存储空间
  • 降低写操作性能
  • 增加维护成本
  • 建议每个表的索引数量不超过5个

4. 索引命名规范

  • 主键索引:pk_表名
  • 唯一索引:uk_表名_列名
  • 普通索引:idx_表名_列名
  • 复合索引:idx_表名_列1_列2

索引创建与管理

1. 索引创建

创建表时创建索引

sql
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE,
    phone VARCHAR(11),
    created_at DATETIME,
    INDEX idx_name (name),
    INDEX idx_created_at (created_at),
    INDEX idx_name_created_at (name, created_at)
);

为现有表创建索引

sql
-- 创建普通索引
CREATE INDEX idx_phone ON users(phone);

-- 创建唯一索引
CREATE UNIQUE INDEX uk_email ON users(email);

-- 创建复合索引
CREATE INDEX idx_name_phone ON users(name, phone);

-- 创建全文索引
CREATE FULLTEXT INDEX ft_content ON articles(content);

2. 索引查询

sql
-- 查看表的索引信息
SHOW INDEX FROM users;

-- 查看表的索引信息(详细)
SHOW CREATE TABLE users;

-- 查询索引使用情况
SELECT * FROM information_schema.statistics WHERE table_schema = 'database_name' AND table_name = 'users';

3. 索引修改与删除

sql
-- 修改索引(先删除后重建)
DROP INDEX idx_phone ON users;
CREATE INDEX idx_phone ON users(phone);

-- 删除索引
DROP INDEX idx_name ON users;

-- 删除主键索引
ALTER TABLE users DROP PRIMARY KEY;

索引使用与优化

1. 索引使用规则

索引有效场景

  • WHERE子句中使用索引列进行精确匹配
  • JOIN操作中使用索引列
  • ORDER BY和GROUP BY使用索引列
  • 覆盖索引查询

索引失效场景

  • 使用!=或<>运算符
  • 使用IS NULL或IS NOT NULL
  • 使用LIKE '%xxx'(前缀模糊查询)
  • 使用函数或表达式操作索引列
  • 类型转换导致索引失效
  • 不遵循最左前缀原则

2. 索引优化建议

1. 使用EXPLAIN分析索引使用

sql
-- 分析查询计划
EXPLAIN SELECT * FROM users WHERE name = '张三';

-- 分析查询计划(详细)
EXPLAIN EXTENDED SELECT * FROM users WHERE name = '张三';

2. 索引覆盖查询

  • 只查询索引包含的列
  • 避免回表操作
  • 提高查询性能
sql
-- 覆盖索引查询示例
SELECT id, name FROM users WHERE name = '张三';
-- 假设idx_name是name列的索引,该查询会使用覆盖索引

3. 前缀索引优化

  • 对长字符串列使用前缀索引
  • 减少索引存储空间
  • 提高索引效率
sql
-- 创建前缀索引
CREATE INDEX idx_email_prefix ON users(email(20));

4. 定期重建索引

  • 解决索引碎片问题
  • 提高索引查询效率
  • 释放存储空间
sql
-- 重建表(同时重建索引)
ALTER TABLE users ENGINE = INNODB;

-- 重建特定索引
DROP INDEX idx_name ON users;
CREATE INDEX idx_name ON users(name);

索引监控与维护

1. 索引使用监控

查看索引使用统计

sql
-- 启用索引使用统计
SET GLOBAL userstat = ON;

-- 查看索引使用情况
SELECT * FROM information_schema.index_statistics WHERE table_schema = 'database_name' AND table_name = 'users';

-- 查看索引命中率
SHOW GLOBAL STATUS LIKE 'Handler_read%';
SHOW GLOBAL STATUS LIKE 'Innodb_rows%';

2. 索引碎片管理

查看表碎片情况

sql
-- 查看表碎片
SELECT table_name, data_free, engine FROM information_schema.tables 
WHERE table_schema = 'database_name' AND table_name = 'users';

优化表(清理碎片)

sql
-- 优化表
OPTIMIZE TABLE users;

-- 或使用ALTER TABLE重建表
ALTER TABLE users ENGINE = INNODB;

3. 冗余索引识别

识别冗余索引

sql
-- 使用pt-duplicate-key-checker工具识别冗余索引
-- 或使用以下SQL查询可能的冗余索引
SELECT 
    t1.table_schema,
    t1.table_name,
    t1.index_name AS redundant_index,
    t2.index_name AS covering_index
FROM 
    information_schema.statistics t1
JOIN 
    information_schema.statistics t2 ON t1.table_schema = t2.table_schema 
    AND t1.table_name = t2.table_name 
    AND t1.index_name != t2.index_name
WHERE 
    t1.table_schema = 'database_name' 
    AND t1.seq_in_index = 1
    AND t2.seq_in_index = 1
    AND t1.column_name = t2.column_name;

常见问题(FAQ)

Q1: 如何判断是否需要创建索引?

A1: 判断是否需要创建索引可以参考以下原则:

  • 表的数据量较大(通常超过1万行)
  • 查询频率较高的列
  • 查询条件中经常使用的列
  • 用于连接操作的列
  • 用于排序和分组的列

Q2: 复合索引的最左前缀原则是什么?

A2: 最左前缀原则是指在复合索引中,只有当查询条件包含索引的最左列时,索引才会被使用。例如,对于复合索引idx_name_age(name, age),查询条件WHERE name = '张三'可以使用索引,而WHERE age = 20则无法使用该索引。

Q3: 为什么有时候索引没有被使用?

A3: 索引没有被使用可能有以下原因:

  • 查询条件不满足索引使用规则
  • 表的数据量太小,全表扫描更快
  • 索引选择性太低
  • 统计信息不准确
  • 发生了类型转换

Q4: 如何优化慢查询中的索引使用?

A4: 优化慢查询中的索引使用可以采取以下措施:

  • 使用EXPLAIN分析查询计划
  • 检查索引是否被正确使用
  • 调整查询语句,使其符合索引使用规则
  • 考虑创建新的索引或修改现有索引
  • 优化索引覆盖查询

Q5: 索引越多越好吗?

A5: 不是。索引越多会带来以下问题:

  • 占用更多的存储空间
  • 降低INSERT、UPDATE、DELETE操作的性能
  • 增加索引维护成本
  • 可能导致优化器选择错误的索引

Q6: 如何维护索引?

A6: 索引维护包括以下方面:

  • 定期分析索引使用情况
  • 清理冗余索引
  • 重建碎片化严重的索引
  • 根据业务变化调整索引
  • 监控索引性能指标

Q7: 全文索引和普通索引有什么区别?

A7: 全文索引和普通索引的主要区别:

  • 适用场景:全文索引适合大文本字段的全文搜索,普通索引适合精确匹配和范围查询
  • 搜索方式:全文索引支持自然语言搜索和布尔搜索,普通索引支持精确匹配和前缀匹配
  • 存储结构:全文索引使用倒排索引,普通索引通常使用B+树结构
  • 性能特点:全文索引在大文本搜索时性能更好,普通索引在精确匹配时性能更好