SQLite Indexed By

SQLite 中,INDEXED BYDELETEUPDATESELECT 语句中的一个 高级特性,用于 强制指定 查询或修改操作使用(或不使用)某个特定索引。

主要用于 性能调优绕过优化器选择错误的索引


一、基本语法

[DELETE | UPDATE | SELECT] ...
INDEXED BY 索引名
...

禁止使用索引

INDEXED BY (无索引名称)  -- 写成空名称

二、三种用法

写法含义
INDEXED BY idx_name强制使用 名为 idx_name 的索引
INDEXED BY ( )INDEXED BY ''强制不使用任何索引(全表扫描)
不写 INDEXED BY查询优化器自动选择 索引

三、实际示例

示例表结构

CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    email TEXT,
    status TEXT,
    created_at DATETIME
);

CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_status ON users(status);

1. 强制使用指定索引

SELECT * FROM users
INDEXED BY idx_users_email
WHERE email = 'alice@example.com';

即使优化器认为 idx_users_status 更优,也强制走 idx_users_email


2. 强制全表扫描(禁止索引)

SELECT * FROM users
INDEXED BY ( )
WHERE status = 'active';

即使有 idx_users_status 索引,也不使用,强制全表扫描
适用于:调试、测试索引效果、避免索引缺陷


3. UPDATE / DELETE 中使用

-- 强制用 email 索引更新
UPDATE users
INDEXED BY idx_users_email
SET status = 'inactive'
WHERE email = 'bob@example.com';

-- 强制不使用索引删除
DELETE FROM users
INDEXED BY ( )
WHERE status = 'deleted';

四、查看执行计划(验证是否生效)

EXPLAIN QUERY PLAN
SELECT * FROM users INDEXED BY idx_users_email WHERE email = 'x';

输出示例

SEARCH TABLE users USING INDEX idx_users_email (email=?)

→ 成功强制使用!


五、什么时候用 INDEXED BY

场景推荐使用
优化器选错索引(导致慢查询)
调试:对比有无索引性能
临时绕过损坏/低效索引
日常查询❌ 应信任优化器

警告:滥用 INDEXED BY 会让 SQL 不可移植,维护成本高!


六、常见错误

-- 错误:索引名拼错
SELECT * FROM users INDEXED BY idx_wrong_name WHERE email = 'x';
-- → 报错:no such index: idx_wrong_name

-- 正确:先确认索引存在
PRAGMA index_list(users);

七、替代方案(推荐)

目标推荐做法
提升性能创建合适索引 + ANALYZE
强制索引仅调试时用 INDEXED BY
避免索引临时测试用 INDEXED BY ()

总结:INDEXED BY 使用建议

用法是否推荐说明
INDEXED BY idx_name⚠️ 仅调试强制走指定索引
INDEXED BY ()⚠️ 仅测试强制全表扫描
不写(默认)✅ 推荐信任优化器

最佳实践

-- 1. 先用 EXPLAIN QUERY PLAN 分析
EXPLAIN QUERY PLAN SELECT ...;

-- 2. 若优化器选错,才考虑临时加:
SELECT ... INDEXED BY idx_correct_one;

-- 3. 长期解决:调整索引设计 + ANALYZE
ANALYZE;

需要我帮你 分析一个慢查询 并判断是否需要 INDEXED BY
把 SQL 和 EXPLAIN QUERY PLAN 结果发我!

文章已创建 2326

发表回复

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

相关文章

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

返回顶部