索引原理与失效场景:把数据库文件剖开看树,再用 40 条 EXPLAIN QUERY PLAN 原文钉死最左前缀
实测:10 万行的表占 909 页、树高 3 层,索引 i_c 占 259 页、树高 2 层,每个索引的字节数都精确等于"页数 × 4096"(+1060864 字节 = 259 页,一页不多);索引的内部页存的是**完整 key + rowid**,表的内部页只存 rowid;(a,b,c) 上 `WHERE b=500` 的计划是 `SCAN`、`a=500 AND c=500` 只用到 `(a=?)`、`a>500 AND b=500` 只用到 `(a>?)`;`lower(name)=…` 16.2 ms,建表达式索引后 0.168 ms(96 倍);`a=5 OR pad='zz'` 走 `MULTI-INDEX OR`(0.135 ms)而 `a=5 OR b=5` 退回 `SCAN`(3.35 ms);TEXT 亲和列拿整数比照样走索引,BLOB 亲和列拿整数比会**静默少行**(4 行只查到 2 行);同一谓词下 50% 命中范围取未索引列 178 ms、走覆盖索引 1.08 ms(165 倍);首列只有 5 个值时 SQLite 不做跳扫,但扫窄索引比扫表快 3.7 倍,与页账本算出来的 3.5 倍对上;4 个索引让 20000 行插入慢 1.34 倍。