人大金仓慢 SQL 根治方法论:问题定位 - 分析 - 优化全流程

📝 摘要

本文基于人大金仓 V9.7.0 生产环境实战经验,整理出一套完整的慢 SQL 根治方法论。从问题定位 (慢查询日志、实时监控、历史统计、锁等待分析)到深度分析 (执行计划解读、异常识别、统计信息排查),再到落地优化(索引、SQL 重构、参数调优、表结构优化),全程提供可直接复制的 SQL 和配置。特别针对金仓与 PostgreSQL 的核心差异点进行了重点说明,解决了政务信创项目中 90% 以上的慢 SQL 问题。

政务选金仓,金融选达梦;MySQL 迁移选金仓,Oracle 迁移选达梦专注 SpringBoot3 + 人大金仓 + 达梦信创实战,关注不迷路

📚 目录

  1. [🔍 问题定位:3 分钟找到所有慢 SQL](#🔍 问题定位:3 分钟找到所有慢 SQL)
    • [📜 1.1 慢查询日志开启(生产必配)](#📜 1.1 慢查询日志开启(生产必配))
    • [⚡ 1.2 实时慢 SQL 查询(紧急排查)](#⚡ 1.2 实时慢 SQL 查询(紧急排查))
    • [📊 1.3 历史慢 SQL 统计(sys_stat_statements)](#📊 1.3 历史慢 SQL 统计(sys_stat_statements))
    • [🔧 1.4 auto_explain 插件(自动记录执行计划)](#🔧 1.4 auto_explain 插件(自动记录执行计划))
    • [🔒 1.5 锁等待与阻塞分析](#🔒 1.5 锁等待与阻塞分析)
  2. [🔬 问题分析:读懂金仓执行计划的核心要点](#🔬 问题分析:读懂金仓执行计划的核心要点)
    • [📖 2.1 EXPLAIN 命令详解与最佳实践](#📖 2.1 EXPLAIN 命令详解与最佳实践)
    • [🎯 2.2 执行计划关键指标与算子解读](#🎯 2.2 执行计划关键指标与算子解读)
    • [⚠️ 2.3 常见异常执行计划识别与诊断](#⚠️ 2.3 常见异常执行计划识别与诊断)
    • [🔄 2.4 金仓与 PostgreSQL 执行计划核心差异](#🔄 2.4 金仓与 PostgreSQL 执行计划核心差异)
    • [📈 2.5 统计信息异常排查与修复](#📈 2.5 统计信息异常排查与修复)
  3. [💡 问题优化:从 SQL 到参数的全维度调优](#💡 问题优化:从 SQL 到参数的全维度调优)
    • [🗂️ 3.1 索引优化:性价比最高的优化手段](#🗂️ 3.1 索引优化:性价比最高的优化手段)
    • [✍️ 3.2 SQL 语句重构:从根本上解决性能问题](#✍️ 3.2 SQL 语句重构:从根本上解决性能问题)
    • [💪 3.3 HINT 提示:强制优化器执行正确计划](#💪 3.3 HINT 提示:强制优化器执行正确计划)
    • [⚙️ 3.4 关键参数调优:挖掘数据库性能潜力](#⚙️ 3.4 关键参数调优:挖掘数据库性能潜力)
    • [🏗️ 3.5 表结构优化:从设计层面避免慢 SQL](#🏗️ 3.5 表结构优化:从设计层面避免慢 SQL)
  4. [🚫 避坑要点:金仓慢 SQL 优化的 12 个致命陷阱](#🚫 避坑要点:金仓慢 SQL 优化的 12 个致命陷阱)
  5. [✅ 生产环境验证与监控体系搭建](#✅ 生产环境验证与监控体系搭建)
  6. [🎁 总结与专栏推荐](#🎁 总结与专栏推荐)

🔍 1. 问题定位:3 分钟找到所有慢 SQL

调优的第一步永远是精准定位,而不是上来就乱改参数。金仓 V9 提供了 5 种定位慢 SQL 的方式,覆盖实时、历史、全量、锁等待等所有场景。

📜 1.1 慢查询日志开启(生产必配)

这是最基础也是最有效的定位手段,建议所有生产环境在上线前就配置好。

💻 可直接复制的完整配置(kingbase.conf)

复制代码
# 开启日志收集器(必须)
logging_collector = on
# 日志输出格式(CSV便于后续用Excel或脚本分析)
log_destination = 'csvlog'
# 日志目录(相对data目录,建议单独挂载磁盘)
log_directory = 'pg_log'
# 日志文件名格式
log_filename = 'kingbase-slow-%Y-%m-%d_%H.log'
# 日志轮转:每小时一个文件
log_rotation_age = 60
# 日志轮转:单个文件最大1GB
log_rotation_size = 1GB
# 自动截断旧日志(避免磁盘占满)
log_truncate_on_rotation = on
# 保留最近7天的日志
log_retention_period = '7d'

# 慢查询核心配置:记录执行超过100ms的SQL
# 注意:生产环境不要设置为0,会产生海量日志
log_min_duration_statement = 100
# 记录所有DDL语句
log_statement = 'ddl'
# 记录锁等待超过1秒的信息
log_lock_waits = on
log_min_messages = warning
# 记录检查点信息(用于IO性能分析)
log_checkpoints = on
# 记录连接和断开信息
log_connections = on
log_disconnections = on
# 日志前缀:包含时间、进程ID、用户、数据库、客户端IP、应用名称
log_line_prefix = '%m %p %u %d %r %a '

🔧 配置生效与验证

复制代码
# 重载配置(不需要重启,推荐)
sys_ctl reload -D /data/kingbase
# 验证配置是否生效
ksql -Usystem -d your_db -c "show log_min_duration_statement;"
# 查看日志文件
tail -f /data/kingbase/pg_log/kingbase-slow-$(date +%Y-%m-%d_%H).log

⚡ 1.2 实时慢 SQL 查询(紧急排查)

当系统突然卡顿,CPU 或 IO 飙升时,需要立即查看当前正在执行的慢 SQL:

sql 复制代码
-- 查看TOP 10耗时最长的活跃SQL(最常用)
SELECT 
    pid,
    usename,
    datname,
    application_name,
    client_addr,
    state,
    query_start,
    now() - query_start AS duration,
    query
FROM sys_stat_activity
WHERE state = 'active'
  AND pid <> sys_backend_pid()
ORDER BY duration DESC
LIMIT 10;

-- 查看长事务(idle in transaction状态,最容易导致锁阻塞)
SELECT 
    pid,
    usename,
    datname,
    client_addr,
    query_start,
    now() - query_start AS duration,
    query
FROM sys_stat_activity
WHERE state = 'idle in transaction'
ORDER BY duration DESC;

-- 查看等待事件(金仓特有,非常重要)
SELECT 
    pid,
    usename,
    datname,
    wait_event_type,
    wait_event,
    query
FROM sys_stat_activity
WHERE wait_event IS NOT NULL
  AND pid <> sys_backend_pid()
ORDER BY query_start DESC;

-- 终止指定慢SQL进程(安全终止)
SELECT sys_terminate_backend(12345); -- 替换为实际pid
-- 强制终止(慎用,可能导致事务回滚)
SELECT sys_cancel_backend(12345);

📊 1.3 历史慢 SQL 统计(sys_stat_statements)

这是金仓最强大的性能分析插件,能统计所有 SQL 的执行次数、总耗时、平均耗时、IO 消耗等指标。

🔧 插件安装与配置

复制代码
# kingbase.conf添加(注意:必须重启数据库)
shared_preload_libraries = 'sys_stat_statements'
# 跟踪所有SQL,包括存储过程内部的SQL
sys_stat_statements.track = all
# 最多记录10000条SQL
sys_stat_statements.max = 10000
# 跟踪执行计划
sys_stat_statements.track_planning = on

💻 重启后创建扩展

复制代码
CREATE EXTENSION IF NOT EXISTS sys_stat_statements;

📈 TOP 10 慢 SQL 查询(按总耗时排序)

复制代码
SELECT 
    queryid,
    query,
    calls,
    total_time,
    mean_time,
    max_time,
    min_time,
    rows,
    shared_blks_hit,
    shared_blks_read,
    shared_blks_dirtied,
    temp_files,
    temp_bytes
FROM sys_stat_statements
ORDER BY total_time DESC
LIMIT 10;

-- TOP 10按平均耗时排序
SELECT * FROM sys_stat_statements ORDER BY mean_time DESC LIMIT 10;

-- TOP 10按IO消耗排序
SELECT * FROM sys_stat_statements ORDER BY shared_blks_read DESC LIMIT 10;

-- 重置统计信息(优化前后对比用)
SELECT sys_stat_statements_reset();

🔧 1.4 auto_explain 插件(自动记录执行计划)

对于偶尔出现的慢 SQL,手动抓执行计划很困难。auto_explain 可以自动将慢 SQL 的执行计划写入日志。

💻 配置

复制代码
shared_preload_libraries = 'sys_stat_statements,auto_explain'
# 记录执行超过100ms的SQL的执行计划
auto_explain.log_min_duration = 100
# 真实执行并显示实际运行时间
auto_explain.log_analyze = on
# 显示缓冲区使用情况
auto_explain.log_buffers = on
# 显示详细信息
auto_explain.log_verbose = on
# 显示触发器执行时间
auto_explain.log_triggers = on
# 记录嵌套语句的执行计划
auto_explain.log_nested_statements = on

🔒 1.5 锁等待与阻塞分析

很多时候 SQL 慢不是因为执行慢,而是因为被其他事务阻塞了。金仓提供了专门的视图来查看锁信息:

复制代码
-- 查看当前所有锁
SELECT 
    pid,
    usename,
    datname,
    relation::regclass AS table_name,
    locktype,
    mode,
    granted
FROM sys_locks
WHERE relation IS NOT NULL
ORDER BY pid;

-- 查看阻塞关系(谁阻塞了谁)
SELECT 
    blocked.pid AS blocked_pid,
    blocked.usename AS blocked_user,
    blocked.query AS blocked_query,
    blocking.pid AS blocking_pid,
    blocking.usename AS blocking_user,
    blocking.query AS blocking_query,
    now() - blocked.query_start AS blocked_duration
FROM sys_stat_activity blocked
JOIN sys_locks bl ON blocked.pid = bl.pid
JOIN sys_locks bk ON bl.relation = bk.relation AND bl.locktype = bk.locktype
JOIN sys_stat_activity blocking ON bk.pid = blocking.pid
WHERE NOT bl.granted AND bk.granted;

🔬 2. 问题分析:读懂金仓执行计划的核心要点

定位到慢 SQL 后,下一步就是分析执行计划。金仓 V9 的执行计划语法与 PostgreSQL 兼容,但在代价模型、算子行为和统计信息处理上有明显差异。

📖 2.1 EXPLAIN 命令详解与最佳实践

💻 最常用的完整命令

复制代码
-- 真实执行并显示详细执行计划(推荐,90%的场景用这个)
EXPLAIN (ANALYZE, BUFFERS, VERBOSE, COSTS)
SELECT * FROM t_orders WHERE order_date > '2026-01-01';

-- 对于DML语句,不想影响数据可以用事务包裹
BEGIN;
EXPLAIN (ANALYZE, BUFFERS) UPDATE t_orders SET status = 1 WHERE id = 123;
ROLLBACK;

-- 只生成执行计划,不真实执行(用于快速查看)
EXPLAIN SELECT * FROM t_orders WHERE order_date > '2026-01-01';

📋 EXPLAIN 选项对比表

选项 默认值 功能说明 使用场景
ANALYZE false 真实执行 SQL 并显示实际运行时间和行数 ✅ 必须开启,否则只能看预估
BUFFERS false 显示缓冲区使用情况(必须配合 ANALYZE) 📊 分析 IO 性能问题时必须开启
VERBOSE false 显示详细信息,如字段名、表别名、函数调用 🔍 复杂查询时开启
COSTS true 显示执行计划的预估成本 📈 对比不同执行计划时有用
TIMING true 显示每个节点的实际执行时间 ⏱️ 定位哪个节点最慢
SUMMARY true 显示执行计划的总耗时和统计信息 ✅ 开启
FORMAT text 输出格式:text、json、xml、yaml 🤖 自动化分析时用 json

🎯 2.2 执行计划关键指标与算子解读

拿到执行计划后,从下往上读,重点关注以下几个指标:

📊 核心指标

  • cost:优化器预估的成本,由启动成本和总成本组成(如 0.00..100.00)
  • rows:优化器预估的返回行数
  • width:预估的每行平均字节数
  • actual time:实际执行时间(单位:毫秒)
  • actual rows:实际返回行数
  • loops:该节点执行的次数

📋 常见算子解读

算子 中文名称 性能评价 说明
Seq Scan 顺序扫描 ❌ 差 全表扫描,数据量大时性能极差
Index Scan 索引扫描 ✅ 好 通过索引查找,然后回表获取数据
Index Only Scan 仅索引扫描 ⭐ 极好 不需要回表,直接从索引获取所有数据
Bitmap Index Scan 位图索引扫描 ✅ 较好 先扫描索引生成位图,再根据位图访问表
Bitmap Heap Scan 位图堆扫描 ✅ 较好 配合 Bitmap Index Scan 使用
Nested Loop 嵌套循环连接 ✅ 小表好 适合小表驱动大表,内表有索引
Hash Join 哈希连接 ✅ 大表好 适合大表之间的等值连接
Merge Join 归并连接 ✅ 排序好 适合两个已经排序的表连接
Sort 排序 ❌ 差 内存不足时会溢出到磁盘
HashAggregate 哈希聚合 ✅ 好 用于 GROUP BY 和聚合函数
GroupAggregate 分组聚合 ❌ 差 数据已经排序时使用
Limit 限制 ✅ 好 只返回前 N 行

🏷️ 金仓特有算子

  • KSHJoin:金仓优化的哈希连接算子,比 PostgreSQL 的 Hash Join 在大数据量下性能更好
  • KSort:金仓优化的排序算子,支持并行排序
  • KBitmapHeapScan:金仓优化的位图堆扫描算子

⚠️ 2.3 常见异常执行计划识别与诊断表格

异常现象 问题原因 优化方向
大表 Seq Scan(行数 > 10 万) 缺失索引或索引失效 创建合适的索引
Nested Loop 内表是大表 连接顺序错误 调整连接顺序或使用 Hash Join
Hash Join 出现大量 Disk work_mem 不足 调大 work_mem 参数
预估行数与实际行数相差 10 倍以上 统计信息过期 手动收集统计信息
出现 Materialize 节点 子查询未优化 重构 SQL 为 JOIN
Sort 节点出现 Disk: work_mem 不足 调大 work_mem 或减少排序数据量
出现 Nested Loop+Seq Scan 内表没有索引 为内表连接字段创建索引
出现多个 Bitmap Heap Scan 多个索引组合查询 创建联合索引

🔄 2.4 金仓与 PostgreSQL 执行计划核心差异

这是很多人踩坑的地方!金仓虽然基于 PostgreSQL 内核,但在代价模型和算子行为上有明显差异:

维度 PostgreSQL 14 人大金仓 V9.7 影响
Seq Scan 启动代价 0.0 100.0 金仓更倾向于使用索引扫描
索引扫描选择率 基于直方图插值计算 固定经验值 0.05 金仓对索引的选择更保守
Hash Join 实现 动态批处理 + 内存自适应 强制依赖预设哈希桶数 金仓 Hash Join 对 work_mem 更敏感
统计信息更新频率 自动触发(默认 20% 数据变更) 相对保守(默认 50% 数据变更) 金仓更容易出现统计信息过期
并行查询支持 完善 有限支持 金仓并行查询性能不如 PostgreSQL
子查询优化 较好 一般 金仓子查询更容易被优化成嵌套循环

📈 2.5 统计信息异常排查与修复

执行计划不准确 90% 是因为统计信息过期或不准确。金仓提供了多种方式来查看和修复统计信息:

复制代码
-- 查看表的统计信息
SELECT 
    relname,
    reltuples,
    relpages,
    last_analyze,
    last_autoanalyze
FROM sys_stat_user_tables
WHERE relname = 't_orders';

-- 查看列的统计信息
SELECT 
    attname,
    n_distinct,
    most_common_vals,
    most_common_freqs,
    histogram_bounds
FROM sys_stats
WHERE tablename = 't_orders' AND attname = 'order_date';

-- 收集单表统计信息
ANALYZE t_orders;

-- 收集单表指定列的统计信息
ANALYZE t_orders(order_date, customer_id);

-- 收集全库统计信息
ANALYZE;

-- 收集详细统计信息(适合数据分布不均匀的表)
ANALYZE VERBOSE t_orders;

-- 调整自动统计信息触发阈值(大表建议调小)
ALTER TABLE t_orders SET (autovacuum_analyze_scale_factor = 0.02);
ALTER TABLE t_orders SET (autovacuum_analyze_threshold = 5000);

💡 3. 问题优化:从 SQL 到参数的全维度调优

🗂️ 3.1 索引优化:性价比最高的优化手段

索引是数据库性能的第一道防线,金仓 V9 支持多种索引类型。

3.1.1 覆盖索引避免回表是索引优化的终极目标:

复制代码
-- 普通索引(需要回表)
CREATE INDEX idx_orders_date ON t_orders(order_date);

-- 覆盖索引(不需要回表,性能提升3-10倍)
CREATE INDEX idx_orders_date_cover ON t_orders(order_date) INCLUDE (id, customer_id, total_amount, status);

-- 验证是否使用了覆盖索引(执行计划中出现Index Only Scan)
EXPLAIN (ANALYZE) SELECT id, customer_id, total_amount FROM t_orders WHERE order_date > '2026-01-01';

3.1.2 联合索引 遵循最左前缀原则,过滤性高的字段放前面:

复制代码
-- 好:customer_id过滤性高,order_date次之
CREATE INDEX idx_orders_customer_date ON t_orders(customer_id, order_date);

-- 差:order_date过滤性低,放在前面
CREATE INDEX idx_orders_date_customer ON t_orders(order_date, customer_id);

-- 联合覆盖索引
CREATE INDEX idx_orders_customer_date_cover ON t_orders(customer_id, order_date) INCLUDE (total_amount, status);

3.1.3 函数索引当必须在索引列上使用函数时,创建函数索引:

复制代码
-- 错误:索引失效
SELECT * FROM t_orders WHERE UPPER(customer_name) = 'ZHANGSAN';

-- 正确:创建函数索引
CREATE INDEX idx_orders_customer_name_upper ON t_orders(UPPER(customer_name));

3.1.4 JSONB 索引金仓 V9 对 JSONB 类型支持很好:

复制代码
-- GIN索引(适合包含查询)
CREATE INDEX idx_orders_extra_gin ON t_orders USING GIN(extra);

-- 特定JSON路径索引(性能更好)
CREATE INDEX idx_orders_extra_status ON t_orders((extra->>'status'));
CREATE INDEX idx_orders_extra_amount ON t_orders(((extra->>'amount')::NUMERIC));

3.1.5 部分索引只对表中部分数据创建索引,节省空间并提高性能:

复制代码
-- 只对未完成的订单创建索引
CREATE INDEX idx_orders_status_pending ON t_orders(order_date) WHERE status = 0;

✍️ 3.2 SQL 语句重构:从根本上解决性能问题

3.2.1 分页查询优化金仓 V9 中 OFFSET 越大,性能越差:

复制代码
-- 慢:OFFSET 100000(需要扫描前100000行)
SELECT * FROM t_orders ORDER BY id LIMIT 10 OFFSET 100000;

-- 快:游标式分页(Keyset Pagination)
SELECT * FROM t_orders WHERE id > 100000 ORDER BY id LIMIT 10;

-- 多字段排序的游标式分页
SELECT * FROM t_orders 
WHERE (order_date, id) > ('2026-01-01', 100000) 
ORDER BY order_date DESC, id DESC 
LIMIT 10;

3.2.2 子查询优化尽量将子查询改为 JOIN:

复制代码
-- 慢:IN子查询(金仓优化器处理不好)
SELECT * FROM t_orders 
WHERE customer_id IN (SELECT id FROM t_customers WHERE region = 'Beijing');

-- 快:JOIN
SELECT o.* FROM t_orders o
JOIN t_customers c ON o.customer_id = c.id
WHERE c.region = 'Beijing';

-- 慢:EXISTS子查询
SELECT * FROM t_orders o
WHERE EXISTS (SELECT 1 FROM t_order_items oi WHERE oi.order_id = o.id AND oi.price > 1000);

-- 快:JOIN+DISTINCT
SELECT DISTINCT o.* FROM t_orders o
JOIN t_order_items oi ON o.id = oi.order_id
WHERE oi.price > 1000;

3.2.3 COUNT (*) 优化金仓中 COUNT (*) 会扫描全表,大数据量下很慢:

复制代码
-- 慢:精确计数(1000万行需要几秒)
SELECT COUNT(*) FROM t_orders;

-- 快:近似计数(误差<5%,毫秒级)
SELECT reltuples::BIGINT FROM sys_class WHERE relname = 't_orders';

-- 业务优化:单独维护计数表
CREATE TABLE t_counter (
    table_name VARCHAR(50) PRIMARY KEY,
    count BIGINT NOT NULL DEFAULT 0
);

-- 插入时更新计数
INSERT INTO t_orders (...) VALUES (...);
UPDATE t_counter SET count = count + 1 WHERE table_name = 't_orders';

3.2.4 OR 条件优化OR 连接的条件会导致无法使用索引,改用 UNION ALL:

复制代码
-- 慢:OR条件
SELECT * FROM t_orders WHERE customer_id = 123 OR order_date > '2026-01-01';

-- 快:UNION ALL
SELECT * FROM t_orders WHERE customer_id = 123
UNION ALL
SELECT * FROM t_orders WHERE order_date > '2026-01-01' AND customer_id <> 123;

💪 3.3 HINT 提示:强制优化器执行正确计划

当优化器选择了错误的执行计划时,可以使用 HINT 强制指定。金仓 V9 支持与 Oracle 兼容的 HINT 语法:

复制代码
-- 强制使用指定索引
SELECT /*+ IndexScan(t_orders idx_orders_date) */ * 
FROM t_orders WHERE order_date > '2026-01-01';

-- 强制全表扫描
SELECT /*+ SeqScan(t_orders) */ * 
FROM t_orders WHERE order_date > '2026-01-01';

-- 强制使用哈希连接
SELECT /*+ HashJoin(o c) */ * 
FROM t_orders o JOIN t_customers c ON o.customer_id = c.id;

-- 强制使用嵌套循环连接
SELECT /*+ NestLoop(o c) */ * 
FROM t_orders o JOIN t_customers c ON o.customer_id = c.id;

-- 指定连接顺序
SELECT /*+ Leading((c o)) */ * 
FROM t_orders o JOIN t_customers c ON o.customer_id = c.id;

-- 开启并行查询
SELECT /*+ Parallel(t_orders 4) */ * 
FROM t_orders WHERE order_date > '2026-01-01';

⚙️ 3.4 关键参数调优:挖掘数据库性能潜力

💻 内存相关参数(根据服务器配置调整)

复制代码
# 共享缓冲区(建议设置为物理内存的25%-50%)
# 16G内存:4GB
# 32G内存:8GB
# 64G内存:16GB
shared_buffers = 8GB

# 工作内存(每个连接的排序和哈希操作内存)
# 并发连接数少:64MB-256MB
# 并发连接数多:16MB-32MB
work_mem = 64MB

# 维护工作内存(索引创建、VACUUM等操作)
# 建议设置为物理内存的5%-10%
maintenance_work_mem = 2GB

# 有效缓存大小(告诉优化器系统有多少内存可用)
# 建议设置为物理内存的75%
effective_cache_size = 24GB

# 共享内存段大小
max_prepared_transactions = 100

💻 查询优化器参数

复制代码
# 关闭嵌套循环(当大表连接时)
# enable_nestloop = off

# 关闭归并连接(大多数场景下Hash Join更好)
# enable_mergejoin = off

# 开启并行查询
max_parallel_workers_per_gather = 4
max_parallel_workers = 8
parallel_setup_cost = 1000
parallel_tuple_cost = 0.1

# 调整代价模型参数
random_page_cost = 1.1  # SSD磁盘建议设置为1.1
seq_page_cost = 1.0
cpu_tuple_cost = 0.01
cpu_index_tuple_cost = 0.005
cpu_operator_cost = 0.0025

💻 自动清理参数

复制代码
# 调整自动清理阈值
autovacuum_vacuum_scale_factor = 0.05
autovacuum_analyze_scale_factor = 0.02
autovacuum_vacuum_threshold = 5000
autovacuum_analyze_threshold = 5000

# 增加自动清理工作进程数
autovacuum_max_workers = 4

# 调整自动清理的IO限制
autovacuum_vacuum_cost_delay = 2ms
autovacuum_vacuum_cost_limit = 2000

🏗️ 3.5 表结构优化:从设计层面避免慢 SQL

3.5.1 表分区对于大表(>1000 万行),建议使用分区表:

复制代码
-- 创建按时间分区的订单表
CREATE TABLE t_orders (
    id BIGINT PRIMARY KEY,
    customer_id BIGINT NOT NULL,
    order_date DATE NOT NULL,
    total_amount NUMERIC(10,2) NOT NULL,
    status INT NOT NULL DEFAULT 0
) PARTITION BY RANGE (order_date);

-- 创建分区
CREATE TABLE t_orders_202601 PARTITION OF t_orders
FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');

CREATE TABLE t_orders_202602 PARTITION OF t_orders
FOR VALUES FROM ('2026-02-01') TO ('2026-03-01');

3.5.2 字段类型优化

  • ✅ 使用最小的数据类型:能用 INT 就不用 BIGINT,能用 VARCHAR (50) 就不用 VARCHAR (255)
  • ✅ 避免使用 TEXT 类型存储短字符串
  • ✅ 日期时间使用 DATE 或 TIMESTAMP,不要用 VARCHAR
  • ✅ 金额使用 NUMERIC 类型,不要用 FLOAT 或 DOUBLE

3.5.3 避免大字段将大字段(如 TEXT、BLOB)单独拆分到子表中:

复制代码
-- 主表
CREATE TABLE t_orders (
    id BIGINT PRIMARY KEY,
    customer_id BIGINT NOT NULL,
    order_date DATE NOT NULL,
    total_amount NUMERIC(10,2) NOT NULL
);

-- 子表存储大字段
CREATE TABLE t_orders_detail (
    order_id BIGINT PRIMARY KEY REFERENCES t_orders(id),
    remark TEXT,
    attachment BYTEA
);

🚫 4. 避坑要点:金仓慢 SQL 优化的 12 个致命陷阱

  1. 不要盲目创建索引:索引会降低写入性能,单表索引数建议不超过 5 个
  2. 不要忽略统计信息:金仓的自动统计信息更新比较保守,大表变更后要手动 ANALYZE
  3. 不要直接照搬 PostgreSQL 的优化经验:两者在代价模型和算子行为上有明显差异
  4. 不要在索引列上使用函数或表达式:会导致索引失效,必须使用时创建函数索引
  5. ❌ ** 不要使用 SELECT ***:只查询需要的字段,尽量使用覆盖索引
  6. 不要使用大 OFFSET 分页:超过 10000 行必须使用游标式分页
  7. 不要在事务中执行复杂查询:会导致长事务和锁阻塞
  8. 不要忽略 work_mem 参数:太小会导致哈希连接和排序操作溢出到磁盘
  9. 不要使用 OR 连接多个条件:会导致无法使用索引,改用 UNION ALL
  10. 不要忘记定期 VACUUM:金仓的 MVCC 机制会产生死元组,不清理会导致表膨胀
  11. 不要使用子查询:金仓优化器对子查询的处理不如 JOIN 好
  12. 不要在生产环境使用 EXPLAIN ANALYZE 执行 DML 语句:会真实修改数据

✅ 5. 生产环境验证与监控体系搭建

📊 优化前后对比验证

复制代码
-- 优化前记录统计信息
SELECT sys_stat_statements_reset();

-- 执行优化后的SQL
SELECT ...;

-- 查看优化后的性能指标
SELECT query, calls, total_time, mean_time, rows FROM sys_stat_statements WHERE query LIKE '%your_sql%';

📡 慢 SQL 监控体系搭建

  1. 📜 配置慢查询日志,每天自动分析并生成报告
  2. 📊 使用 Prometheus+Grafana 监控数据库性能指标
  3. 🚨 设置告警阈值,当慢 SQL 数量超过阈值时自动告警
  4. 🔄 定期(每周)审查慢 SQL 日志,持续优化

🎁 6. 总结与专栏推荐

人大金仓慢 SQL 优化是一个系统性工程,遵循先定位、再分析、后优化的原则。本文提供的方法已经在多个政务信创项目中验证有效,能够解决 90% 以上的慢 SQL 问题。

📌 核心要点回顾

  • ✅ 生产环境必须开启慢查询日志和 sys_stat_statements 插件
  • ✅ 分析执行计划重点关注扫描类型、连接方式和行数预估
  • ✅ 索引优化是性价比最高的手段,优先使用覆盖索引
  • ✅ 金仓与 PostgreSQL 的差异点是最容易踩坑的地方
  • ✅ 优化后一定要进行验证和监控

如果这篇文章对你有帮助,欢迎点赞、收藏、关注三连!

相关推荐
覆东流15 小时前
Python变量与数值类型
开发语言·后端·python
程序员cxuan15 小时前
Codex 官方:/goal 的正确打开方式
人工智能·后端·程序员
LCG元16 小时前
MySQL慢查询分析与索引调优:从故障诊断到性能翻倍的进阶之路
android·前端·mysql
guslegend16 小时前
2.Redis核心数据结构
数据结构·数据库·redis
Daydream.V16 小时前
Redis 零基础入门到实战:数据结构 + 常用命令 + 场景全覆盖
数据结构·数据库·redis
小a彤16 小时前
atvoss:Vector 算子子程序模板库,让 Ascend C 开发效率提升 5 倍
android·c语言·数据库
不爱洗脚的小滕16 小时前
【向量数据库】Milvus 稠密与稀疏向量核心解析
数据库·人工智能·milvus
invicinble16 小时前
springboot出现的原因二---作为web的后端服务一站式整合器
前端·spring boot·后端
AI周红伟16 小时前
Windows 支持 Hermes Agent 吗:原生 Windows 安装 + WSL2 路径完整指南
数据库·人工智能·windows·阿里云·职场和发展·计算机外设