你的电商系统订单表已经攒了5000万行数据。运营后台每次打开"待处理订单"页面都要转圈十几秒,你加了索引却没什么改善——问题可能在于,你建的索引类型根本不对。
大多数开发者知道索引能加速查询,但给每个过滤字段都堆上基础索引,结果往往是存储膨胀、写入变慢,性能却没提升。真正的高手懂得根据查询场景选择索引类型。这篇用PostgreSQL演示的实战指南,同样适用于MySQL、SQL Server等主流数据库。
![]()
假设你的orders表长这样:订单ID、客户ID、状态(pending/shipped/delivered/cancelled)、金额、创建时间、地区。5000万行里,98%是已完成或取消的订单,只有2%处于待处理或发货中——这种极度倾斜的数据分布,正是普通索引失效的典型场景。
![]()
局部索引:只索引你查的那部分
运营后台的高频查询是"拉取所有pending和shipped订单,按时间倒序排"。如果在status字段建普通索引,数据库会为全部5000万行建立索引项,其中4900万行永远不会被这条查询用到。
局部索引的解法很直接:只给符合条件的行建索引。
CREATE INDEX idx_orders_active ON orders (created_at DESC) WHERE status IN ('pending', 'shipped');
这样索引只覆盖约100万行活跃订单,体积缩小98%,更容易常驻内存。即使总表持续增长,已完成订单也不会污染这个索引。执行计划对比很直观:之前是全表扫描5000万行(cost=1245000),现在是索引扫描100万条目(cost=9834),成本相差两个数量级。
局部索引最适合三类场景:数据分布高度倾斜、频繁查询"活跃/开放"记录而历史数据持续累积、以及需要"非空值唯一约束"(如CREATE UNIQUE INDEX ON users (email) WHERE email IS NOT NULL)。
复合索引:字段顺序决定生死
复合索引覆盖多个字段,但字段顺序不是随意的。核心规则是:最左前缀匹配。索引(a,b,c)可以加速WHERE a=1、WHERE a=1 AND b=2、WHERE a=1 AND b=2 AND c=3,但无法单独用于WHERE b=2或WHERE c=3。
假设常见查询是按地区查某时间段的订单:WHERE region='APAC' AND created_at > '2024-01-01'。如果建索引(created_at, region),数据库能用到created_at部分,但region的过滤要在回表后做;反过来建(region, created_at),两个条件都能在索引内完成过滤,效率更高。
更隐蔽的陷阱是排序。如果查询是WHERE region='APAC' ORDER BY created_at DESC,索引(region, created_at DESC)能避免额外的排序操作;而(created_at DESC, region)虽然也能过滤,但取出数据后还要重新排序。
![]()
覆盖索引:彻底消灭回表
即使命中索引,如果SELECT的字段不在索引里,数据库还得回主表查数据——这叫"回表",是随机IO的大户。覆盖索引的思路是:把查询需要的所有字段都塞进索引,让数据库只读索引就能返回结果。
回到运营后台的例子,查询是SELECT id, customer_id, total FROM orders WHERE status IN ('pending', 'shipped') ORDER BY created_at DESC。如果建局部索引时加上INCLUDE子句:
CREATE INDEX idx_orders_active_covering ON orders (created_at DESC) INCLUDE (id, customer_id, total) WHERE status IN ('pending', 'shipped');
PostgreSQL可以直接从索引返回全部字段,无需触碰主表。执行计划里的"Index Only Scan"比"Index Scan"更进一步,在IO密集型场景提升显著。
INCLUDE的妙处在于:id、customer_id、total只作为"载荷"存储,不参与索引排序,因此不影响索引维护成本,也不限制查询时的字段顺序。
怎么选?一张决策表
数据倾斜严重、只查小部分行 → 局部索引
多字段联合过滤、有排序需求 → 复合索引(仔细排字段顺序)
SELECT字段固定、想彻底消灭回表 → 覆盖索引
这三种策略可以叠加使用。上面的例子就是局部+覆盖的组合,把5000万行的大表查询降到了百万级索引的内存扫描。
索引不是越多越好,每个索引都在写入时产生维护成本。好的数据库设计是在查询模式和存储开销之间找平衡——而选对索引类型,是这个平衡里最被低估的杠杆。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.