文章列表
3 分钟阅读

PostgreSQL 基础:索引、事务、慢查询怎么理解

更新说明:补充 PostgreSQL 基础和慢查询排查思路。


系列:Python Web 工程实践

第 8 / 8 篇

  1. Python Web 项目配置管理:环境变量、.env 和生产配置怎么拆
  2. Python Web 项目如何连接数据库:SQLAlchemy、Django ORM、迁移怎么选
  3. Alembic 数据库迁移入门:表结构变更怎么安全上线
  4. Django 数据库迁移实战:makemigrations 和 migrate 背后的坑
  5. FastAPI 项目测试指南:pytest、TestClient、依赖覆盖怎么用
  6. Django 测试入门:Model、View、API 测试怎么写
  7. FastAPI 分层架构:router、service、repository 怎么拆
  8. PostgreSQL 基础:索引、事务、慢查询怎么理解

很多 Web 项目一开始只关心“数据库能不能连上”,后来才会遇到查询慢、重复数据、事务不一致、迁移变慢这些问题。PostgreSQL 不需要一开始学得很深,但有几个基础概念越早理解越好。

这篇只讲 Web 项目最常用的三件事:索引、事务、慢查询。

索引不是越多越好

索引可以让查询更快,但它不是免费午餐。每多一个索引,写入和更新时数据库都要维护它。

常见的适合建索引的字段:

  • 经常出现在 where 条件里的字段
  • 经常用于排序的字段
  • 外键字段
  • 唯一约束字段
  • 高频组合查询字段
create index idx_articles_status_created_at
on articles (status, created_at desc);

如果接口经常这样查:

select *
from articles
where status = 'published'
order by created_at desc
limit 20;

上面的组合索引就可能有用。

用 explain 看执行计划

不要靠感觉判断索引是否生效。先看执行计划。

explain analyze
select *
from articles
where status = 'published'
order by created_at desc
limit 20;

常见关键词:

  • Seq Scan:顺序扫描整张表
  • Index Scan:使用索引扫描
  • Bitmap Index Scan:先用索引找位置,再回表
  • Sort:额外排序

小表出现 Seq Scan 不一定是坏事。数据量很小时,全表扫可能比走索引更便宜。

事务解决什么问题

事务保证一组操作要么都成功,要么都失败。最典型的例子是创建订单和扣库存。

begin;
insert into orders (user_id, total) values (1, 99);
update products set stock = stock - 1 where id = 10;
commit;

如果中间出错,可以回滚:

rollback;

在 Web 项目里,事务边界要清楚。不要在一个事务里做很慢的外部请求,也不要让事务跨越太多不相关逻辑。

唯一约束比代码判断更可靠

比如用户名不能重复,不能只靠代码先查一遍。

create unique index users_email_key on users (email);

代码里的“先查再插入”在并发下可能失效。数据库唯一约束才是最终防线。

慢查询先看三件事

排查慢查询时,我会先看:

  1. 数据量是否比预期大
  2. where 和 order by 是否有合适索引
  3. 是否查出了太多不需要的列或行

比如接口只展示标题和时间,就不要 select *

select id, title, created_at
from articles
where status = 'published'
order by created_at desc
limit 20;

分页也要注意。很深的 offset 会越来越慢。

select id, title
from articles
order by id
limit 20 offset 100000;

数据量大时,可以考虑基于游标的分页。

Web 项目里常见的坑

第一个坑是 N+1 查询。列表页查出 20 篇文章,然后每篇文章再单独查作者,就会变成 21 次查询。

第二个坑是模糊搜索。like '%keyword%' 很难用普通 B-tree 索引优化,需要考虑全文搜索或 trigram 索引。

第三个坑是迁移时给大表加字段、加索引。数据库迁移可以接着看 Alembic 数据库迁移入门:表结构变更怎么安全上线Django 数据库迁移实战:makemigrations 和 migrate 背后的坑

总结

PostgreSQL 的基础不只是 SQL 语法。对 Web 项目来说,索引决定查询路径,事务决定数据一致性,慢查询排查决定线上稳定性。

刚开始不需要把数据库调优学得很深,但要养成两个习惯:用约束保护数据,用 explain analyze 验证判断。这样遇到性能问题时,至少不会只靠猜。