索引为什么会"失效"
在 KingbaseES 中,索引本身不会物理失效,但优化器在某些情况下会选择不走索引,或索引因膨胀效率低下。常见场景如下:
场景一:对索引列进行函数或隐式类型转换
-- 错误写法:对索引列用函数,导致索引失效 SELECT * FROM users WHERE upper(email) = 'ADMIN@EXAMPLE.COM'; -- 正确写法:使用函数索引 CREATE INDEX idx_users_email_upper ON users (upper(email)); -- 或改写 SQL 避免对列用函数 SELECT * FROM users WHERE email = lower('ADMIN@EXAMPLE.COM');
场景二:LIKE 前缀通配符
-- 可走索引(前缀匹配) SELECT * FROM products WHERE name LIKE 'iPhone%'; -- 无法走普通 B-tree 索引(前导通配符) SELECT * FROM products WHERE name LIKE '%iPhone%'; -- 解决方案:创建 GIN 全文索引 CREATE INDEX idx_products_name_gin ON products USING GIN (to_tsvector('simple', name));
场景三:统计数据偏差导致优化器误判
-- 强制分析后观察执行计划是否改变 ANALYZE VERBOSE orders; -- 提高特定列的统计样本量(默认 100) ALTER TABLE orders ALTER COLUMN status SET STATISTICS 500;
场景四:索引膨胀
频繁增删数据后,B-tree 索引会产生膨胀(碎片),降低扫描效率。
-- 检测索引膨胀(需安装 pgstattuple 扩展) CREATE EXTENSION IF NOT EXISTS pgstattuple; SELECT * FROM pgstatindex('idx_orders_status'); -- avg_leaf_density < 50% 表示严重膨胀 -- 不停机重建索引 REINDEX INDEX CONCURRENTLY idx_orders_status; -- 重建表上所有索引 REINDEX TABLE CONCURRENTLY orders;
REINDEX CONCURRENTLY 不会持有排他锁,可在业务运行期间执行,但速度较慢,且需要额外磁盘空间(约等于原索引大小)。