定位慢查询
金仓数据库提供 sys_stat_statements 扩展,可统计 SQL 的执行频率、总耗时和平均耗时。
-- 启用扩展(需在 kingbase.conf 中配置 shared_preload_libraries) CREATE EXTENSION IF NOT EXISTS sys_stat_statements; -- 查询耗时 TOP 10 的 SQL SELECT total_exec_time / calls AS avg_ms, calls, total_exec_time, query FROM sys_stat_statements ORDER BY total_exec_time DESC LIMIT 10;
也可开启慢查询日志,直接在日志中捕获慢 SQL:
# 在 kingbase.conf 中设置(单位:ms) log_min_duration_statement = 1000 # 超过 1 秒记录日志 log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '
使用 EXPLAIN ANALYZE 分析执行计划
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) SELECT * FROM orders o JOIN customers c ON o.customer_id = c.id WHERE o.status = 'pending' AND o.created_at > '2025-01-01';
重点关注执行计划中的 Seq Scan(全表扫描)节点。若出现在大表上,通常意味着索引缺失或未被使用。
常见慢查询原因与优化方案
原因一:缺少索引
-- 为高频过滤列添加索引 CREATE INDEX CONCURRENTLY idx_orders_status_created ON orders (status, created_at); -- 对于多列查询,注意索引列顺序:选择性高的列放前面
原因二:统计信息过旧
-- 手动更新统计信息 ANALYZE orders; -- 查看统计信息最后更新时间 SELECT relname, last_analyze, last_autoanalyze FROM sys_stat_user_tables WHERE relname = 'orders';
原因三:连接池不足导致排队
-- 查看当前连接数 SELECT count(*), state FROM sys_stat_activity GROUP BY state; -- 查看等待锁的会话 SELECT pid, query, wait_event_type, wait_event, state FROM sys_stat_activity WHERE wait_event_type = 'Lock';
原因四:大表缺少分区
对于超过 1000 万行的历史数据表,建议按时间字段进行范围分区,将查询限定在特定分区内。
-- 创建按年分区的表 CREATE TABLE orders_2025 PARTITION OF orders FOR VALUES FROM ('2025-01-01') TO ('2026-01-01');
性能参数调优参考
| 参数 | 推荐值(8C 32G) | 说明 |
|---|---|---|
| shared_buffers | 8GB | 共享缓冲区,建议为内存的 25% |
| work_mem | 64MB | 每个排序/哈希操作的内存 |
| maintenance_work_mem | 1GB | VACUUM/CREATE INDEX 使用的内存 |
| effective_cache_size | 24GB | 操作系统缓存估算值(影响执行计划) |
| max_parallel_workers_per_gather | 4 | 单查询并行度 |