pg_stat_statements 是 PostgreSQL 自带的一个扩展,可以让你看到数据库里到底都发生了哪些查询,以及它们的表现。说白了,这就是个安静但很细心的小助手,会记录每一步:执行了哪些 SQL 查询、花了多少时间、被执行了多少次、对系统压力有多大。
为啥要用它?首先,是为了找出有问题的查询。有时候数据库卡顿不是因为一个“坏蛋”,而是因为有十几个一样的重查询被疯狂执行。其次,这些统计能帮你看到到底哪些查询在吃资源——CPU、内存、磁盘。你还能知道索引是不是像你想的那样在工作:有的地方可能根本没用上索引,有的地方反而索引不够。
pg_stat_statements 让你不用猜,直接看到真实的数据——然后根据这些数据做出判断和优化。
怎么找慢查询?
现在开始有意思了!用 pg_stat_statements 这张表,我们可以找出那些执行很慢或者压力很大的查询。
核心思路:
pg_stat_statements 里的每一行都代表一个查询的统计信息。查询会按文本分组(就是 query 字段),每个查询会统计这些指标:
total_time—— 查询总共花了多少时间,单位是毫秒。calls—— 查询被执行了多少次。mean_time—— 查询平均执行时间(total_time / calls)。rows—— 查询每次返回了多少行。
简单分析的例子
我们来找一下平均执行时间最长的慢查询:
SELECT
query,
mean_time,
calls,
rows
FROM
pg_stat_statements
ORDER BY
mean_time DESC
LIMIT 5;
这个查询会显示执行最慢的 TOP-5 查询。注意 mean_time 字段:如果这里的值超过 500-1000 毫秒,那就说明这些查询该优化了。
慢查询分析例子
我们来分析个例子:
这是上面那个查询的结果:
| query | mean_time | calls | rows |
|---|---|---|---|
| SELECT * FROM orders WHERE status = 'new'; | 1234.56 | 10 | 10000 |
| SELECT * FROM products | 755.12 | 5000 | 100 |
| SELECT * FROM customers WHERE id = $1 | 543.21 | 1000 | 1 |
我们看到了啥?
对 orders 表的查询:执行次数很少(才 10 次),但每次都拉出 1 万行。估计表很大,而且没用上索引。
对 products 表的查询:被执行了几千次,可能在应用里被循环调用。每次只查 100 行,但因为次数太多,这个查询也可能有问题。
对 customers 表的查询:执行很快(543 毫秒),但调用次数太多了。
慢查询优化
现在我们找到了有问题的查询,接下来要用 EXPLAIN ANALYZE 看下它们的执行计划。比如对 orders 表的查询:
EXPLAIN ANALYZE
SELECT * FROM orders WHERE status = 'new';
我们能看到啥?
Seq Scan:如果查询用的是全表扫描,那就要加索引了:
CREATE INDEX idx_orders_status ON orders (status);
过滤条件问题: 如果查询拉出来的数据太多,得重新考虑下 SQL。也许要加点条件或者加个限制:
SELECT * FROM orders WHERE status = 'new' LIMIT 100;
按执行时间输出统计
有时候有问题的查询并不明显。比如那些经常调用函数或者子查询的 SQL。这种情况可以看 total_time 字段:
SELECT
query,
total_time,
calls,
mean_time
FROM
pg_stat_statements
ORDER BY
total_time DESC
LIMIT 10;
这个查询会显示总耗时最多的“最贵”查询。
索引优化
很多慢查询其实就是缺索引。用 pg_stat_statements 看看哪些查询没用上索引。如果你发现有很多带相同过滤条件(比如 status 字段)的慢查询,就加个对应的索引:
CREATE INDEX idx_orders_status ON orders (status);
加完索引后,再用 EXPLAIN ANALYZE 检查下查询性能。
用 pg_stat_statements,你可以高效地监控查询性能,找出“瓶颈”,提升数据库的表现。记住,越早开始分析查询,后面优化系统就越轻松。
GO TO FULL VERSION