如果说执行计划是诊断慢SQL的“CT扫描”,那么索引就是对其进行治疗的“特效药”。在磐维数据库中,合理地创建和使用索引,往往能让查询性能提升几个数量级。然而,索引不是免费的,它会增加插入、更新、删除操作的开销,并占用额外存储空间。因此,理解并掌握索引的艺术至关重要。
一、磐维数据库(openGauss)常用索引类型
B-Tree索引: 默认和最通用的索引类型。适用于等值查询(=)、范围查询(<, >, BETWEEN)和排序(ORDER BY)。几乎所有场景的首选。
位图索引(Bitmap Index): 适用于低基数列( distinct值很少的列,如性别、状态标志)。对于多个低基数列的AND/OR条件查询,位图索引可以通过位运算高效合并,性能远超B-Tree。但请注意,在位图索引列上进行更新操作,锁粒度较大,高并发OLTP场景需谨慎。
GIN(通用倒排索引): 专为处理多值类型(如数组、全文检索、JSONB)而设计。如果你需要查询JSONB文档中的某个键值,或者数组是否包含某个元素,GIN索引是最佳选择。
GiST(通用搜索树索引): 支持多种数据结构和查询,如几何数据类型、范围类型和全文检索。是GIN的补充,在某些复杂数据类型上表现更优。
二、索引设计最佳实践
选择性原则: 索引应该建在高选择性的列上。选择性 = 不同值数目 / 总行数。越接近1,选择性越好。像“状态”这种只有几个值的列,通常不适合单独建B-Tree索引,但可以考虑位图索引。
复合索引与列顺序:
复合索引的列顺序至关重要。应将最常用作查询条件且选择性最高的列放在最左边。
遵循左前缀匹配原则。对于索引 (a, b, c),它可以优化 WHERE a=?、WHERE a=? AND b=?、WHERE a=? AND b=? AND c=? 的查询,但无法优化 WHERE b=? 或 WHERE c=? 的查询。
如果查询中包含了 ORDER BY a, b,而索引正好是 (a, b),那么数据库就可以直接利用索引的有序性,避免昂贵的排序操作。
覆盖索引的魔力:
如果一个索引包含了查询所需要的全部字段,数据库就无需回表(访问堆表),可以极大地提升性能,这被称为“仅索引扫描”(Index Only Scan)。
示例:
sql
-- 表结构: sales(sale_id, product_id, sale_date, amount)
-- 常见查询:
SELECT product_id, sale_date FROM sales WHERE sale_date BETWEEN '2023-01-01' AND '2023-01-31';
-- 优化:创建一个覆盖索引
CREATE INDEX idx_sales_date_product ON sales(sale_date, product_id);
-- 执行此查询时,磐维数据库会使用Index Only Scan,直接从索引中获取数据,效率极高。
避免索引失效的陷阱:
对索引列使用函数或计算: WHERE upper(name) = 'ALICE' 会使 idx_name 失效。解决方案:创建函数索引 CREATE INDEX idx_upper_name ON employees(upper(name));。
隐式类型转换: 如果列是字符串类型,但查询写 WHERE id = 123(数字),会导致索引失效。应确保类型一致 WHERE id = '123'。
使用 LIKE 通配符开头: WHERE name LIKE '%son' 无法使用索引,而 WHERE name LIKE 'John%' 可以。
三、索引维护与诊断
索引膨胀: 随着表的更新,索引会产生碎片和空页,导致索引体积变大、性能下降。定期使用 REINDEX 或 VACUUM FULL(会锁表)重建索引,或者在业务低峰期并发重建 REINDEX CONCURRENTLY(openGauss支持,不影响读写)。
监控未使用的索引: 索引如果只写不用,就是纯粹的负担。可以通过查询 PG_STAT_ALL_INDEXES 视图来监控索引的使用情况。
sql
SELECT s.relname AS table_name, i.indexrelname AS index_name, s.idx_scan
FROM pg_stat_user_indexes s
JOIN pg_index i ON s.indexrelid = i.indexrelid
WHERE s.idx_scan = 0; -- 查找从未被扫描过的索引
对于这些“僵尸索引”,应果断考虑删除。
总结:
索引是一把双刃剑。精妙的索引设计能化腐朽为神奇,而盲目创建索引则会拖慢整个系统。通过理解不同类型的索引特性,遵循选择性、左前缀和覆盖索引等原则,并定期进行维护和监控,我们就能让索引真正成为提升磐维数据库性能的利器。下一篇文章,我们将跳出索引,从SQL语句本身出发,探讨如何通过重写和重构来优化查询。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




