Postgres多租户架构下按Schema排查慢查询及参数值问题
1. Schema隔离多租户下查看各租户慢查询
可以直接通过Postgres实现,核心是利用pg_stat_statements扩展提供的schemaname字段,该字段会记录查询所属的Schema,以此区分不同租户。
实现方法:
- 先确认
pg_stat_statements已启用:检查postgresql.conf中shared_preload_libraries包含pg_stat_statements,若未配置则修改后重启服务(或用ALTER SYSTEM设置后执行SELECT pg_reload_conf();重载配置)。 - 按租户Schema过滤统计慢查询:
SELECT schemaname, round(total_exec_time::numeric, 2) AS total_time, calls, round(mean_exec_time::numeric, 2) AS mean, round((100 * total_exec_time / sum(total_exec_time::numeric) OVER ())::numeric, 2) AS percentage_cpu, query FROM pg_stat_statements -- 筛选目标租户Schema WHERE schemaname IN ('company_a', 'company_b') ORDER BY total_exec_time DESC LIMIT 5; - 按Schema分组汇总整体慢查询情况:
SELECT schemaname, sum(total_exec_time) AS total_time, count(*) AS query_count, max(mean_exec_time) AS slowest_mean_time FROM pg_stat_statements WHERE schemaname != 'public' -- 排除公共Schema GROUP BY schemaname ORDER BY total_time DESC;
2. 查看慢查询的具体参数值
pg_stat_statements默认会把查询参数替换为$1、$2这类占位符,目的是聚合结构相同的查询,避免重复统计。如果需要查看具体参数值,可通过以下两种方式实现:
方式一:通过Postgres日志记录带参数的慢查询
修改postgresql.conf相关配置:
# 记录执行时间超过500毫秒的查询(可根据业务调整阈值) log_min_duration_statement = 500 # 确保日志包含实际参数值 log_statement = 'none' -- 仅记录慢查询,设为'all'会记录所有查询,性能开销较大 log_line_prefix = '%t [%p]: [%c-%l] user=%u,db=%d,app=%a ' -- 可选,添加日志上下文信息
配置生效后,慢查询会被写入Postgres日志文件,日志内容将包含完整的带参数的SQL语句。
方式二:使用auto_explain扩展记录参数与执行计划
auto_explain可同时记录慢查询的执行计划和参数:
- 修改
postgresql.conf启用扩展:shared_preload_libraries = 'pg_stat_statements, auto_explain' auto_explain.log_min_duration = 500 -- 慢查询时间阈值 auto_explain.log_parameters = on -- 开启参数记录 auto_explain.log_analyze = on -- 可选,记录执行时的实际统计数据 - 重载配置使生效:
SELECT pg_reload_conf();
之后,慢查询的参数和执行计划会被写入Postgres日志。
注意:记录参数会带来一定性能开销,且参数可能包含敏感数据(如用户密码),需严格控制日志的访问权限,防止数据泄露。
内容的提问来源于stack exchange,提问作者mamcx
相关产品推荐
相关产品推荐

