SQLite 索引(Index)

SQLite 中,索引(Index) 是提升 查询性能 的关键数据库对象,尤其在 WHEREJOINORDER BY 等操作频繁的列上。


一、什么是索引?

索引是一个 独立的数据结构(通常是 B 树),存储某列(或多列)的值及其对应的行位置(ROWID),加速数据检索

类比:书的目录 → 快速找到章节页码


二、创建索引

基本语法

CREATE [UNIQUE] INDEX [IF NOT EXISTS] 索引名
ON 表名 (列名1 [ASC|DESC], 列名2, ...);
选项说明
UNIQUE确保索引列值唯一(违反时报错)
IF NOT EXISTS避免重复创建
ASC / DESC排序方向(默认 ASC

示例

-- 单列索引
CREATE INDEX idx_users_email ON users(email);

-- 多列索引(复合索引)
CREATE INDEX idx_orders_user_date ON orders(user_id, order_date DESC);

-- 唯一索引
CREATE UNIQUE INDEX idx_users_email_unique ON users(email);

三、索引类型

类型说明
普通索引CREATE INDEX
唯一索引CREATE UNIQUE INDEX
复合索引多列联合索引
部分索引只对满足条件的行建索引
表达式索引对表达式结果建索引

四、高级索引

1. 部分索引(Partial Index)

只为符合 WHERE 条件的行创建索引,节省空间

CREATE INDEX idx_active_users ON users(email)
WHERE status = 'active';

仅对 status='active' 的用户建立 email 索引


2. 表达式索引(Expression Index)

计算结果 建索引。

CREATE INDEX idx_users_name_lower ON users(LOWER(name));

-- 查询时必须匹配表达式
SELECT * FROM users WHERE LOWER(name) = 'alice';
-- 才会命中索引

3. 覆盖索引(Covering Index)

索引包含查询所需 所有列,无需回表。

CREATE INDEX idx_covering ON orders(user_id, order_date, total);

SELECT user_id, order_date, total
FROM orders
WHERE user_id = 123;
-- 直接从索引读取数据,超快!

五、查看索引

-- 查看所有索引
PRAGMA index_list(表名);

-- 查看索引结构
PRAGMA index_info(索引名);

-- 查看所有索引 SQL
SELECT name, sql FROM sqlite_master WHERE type = 'index';

六、删除索引

DROP INDEX IF EXISTS 索引名;

七、自动索引?主键 & UNIQUE

情况自动创建索引
PRIMARY KEY自动在主键列建唯一索引
UNIQUE 约束自动建唯一索引
INTEGER PRIMARY KEY就是 ROWID 别名,无额外索引
CREATE TABLE users (
    id INTEGER PRIMARY KEY,     -- 自动索引
    email TEXT UNIQUE           -- 自动唯一索引
);

八、索引使用分析(必备技能)

EXPLAIN QUERY PLAN 检查是否命中索引

EXPLAIN QUERY PLAN
SELECT * FROM users WHERE email = 'alice@example.com';

输出解读

输出含义
SEARCH TABLE users USING INDEX idx_users_email命中索引
SCAN TABLE users全表扫描,慢!

九、最佳实践(Best Practices)

建议说明
WHEREJOINORDER BY 频繁使用的列建索引高频查询列优先
避免在低选择性列建索引(如 gender几乎无效
复合索引遵循 最左前缀原则(a,b) 支持 aa,b 查询,不支持单独 b
定期用 ANALYZE 更新统计信息ANALYZE; 帮助优化器选择索引
写多于读?慎用索引插入/更新会变慢

十、复合索引顺序原则(重要!)

CREATE INDEX idx_orders_user_status ON orders(user_id, status, created_at);

可加速的查询

  • WHERE user_id = ?
  • WHERE user_id = ? AND status = ?
  • WHERE user_id = ? AND status = ? ORDER BY created_at

不可加速

  • WHERE status = ? (跳过 user_id
  • WHERE created_at = ?

原则:把 过滤性最强等值查询 的列放最左


十一、维护命令

-- 重新构建所有索引(修复碎片)
REINDEX;

-- 更新统计信息(优化查询计划)
ANALYZE;

-- 检查索引是否损坏
PRAGMA integrity_check;

总结:索引决策表

场景是否建索引
WHERE 条件列
JOIN 的连接键
ORDER BY✅(尤其配合 LIMIT
小表(<1000 行)❌ 不必要
频繁插入/更新列⚠️ 权衡性能
布尔值/枚举低基数列❌ 无效

示例:电商优化

-- 高频查询:用户订单列表
CREATE INDEX idx_orders_user_created ON orders(user_id, created_at DESC);

-- 高频查询:按状态筛选
CREATE INDEX idx_orders_status ON orders(status) WHERE status != 'deleted';

-- 覆盖索引:避免回表
CREATE INDEX idx_orders_cover ON orders(user_id, created_at, total, status);

需要我帮你 分析某个 SQL 是否会命中索引
为你的表设计最优索引方案?把表结构发我!

文章已创建 2326

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部