查询优化
查询优化的目标是减少扫描数据量、降低排序和关联成本,并让数据库使用合适的索引。优化前应先定位慢查询,再根据执行计划处理瓶颈。
使用 EXPLAIN
EXPLAIN 可以查看查询计划,EXPLAIN ANALYZE 会实际执行 SQL 并输出耗时。
explain analyze
select id, title
from public.todos
where user_id = 'user-1'
order by created_at desc
limit 20;
生产环境使用 EXPLAIN ANALYZE 前要谨慎,因为它会真实执行语句。
创建合适索引
为高频过滤、排序和关联字段创建索引。
create index todos_user_created_idx
on public.todos (user_id, created_at desc);
组合索引的字段顺序很重要。通常把等值过滤字段放前面,把排序字段放后面。
更多索引类型请参考 索引管理。
避免全表扫描
常见全表扫描原因包括:
- 过滤字段没有索引。
- 对索引字段使用函数或类型转换。
- 查询条件选择性太低。
- 统计信息过期。
analyze public.todos;
分页优化
偏移分页在深页时会越来越慢。
select id, title
from public.todos
order by id
limit 20 offset 10000;
大数据量列表建议使用游标分页。
select id, title
from public.todos
where id > 10000
order by id
limit 20;
RLS 性能
RLS 策略会参与每次查询。策略字段应创建索引,并优先使用 (select auth.uid()) 缓存当前用户值。
create index todos_user_id_idx on public.todos(user_id);
create policy "read own rows"
on public.todos
for select to authenticated
using (user_id = (select auth.uid()));
更多 RLS 优化建议请参考 基础权限。
优化流程
- 记录慢 SQL、参数和执行时间。
- 使用
EXPLAIN查看是否全表扫描、排序或嵌套循环过重。 - 补充或调整索引。
- 执行
analyze更新统计信息。 - 对比优化前后的执行计划和耗时。
不要只凭经验添加大量索引。索引会增加写入成本和存储成本,应围绕真实查询模式设计。