目录
在 5 亿级数据量的分区表上创建索引需要谨慎操作,但不会导致数据库崩溃,只要合理规划资源和操作方式。以下是详细分析和安全操作指南:
1. 存储空间占用分析
索引大小估算公式:
索引大小 ≈ 表行数 × (索引列大小 + 8字节) × 1.3
具体案例计算:
表名 | 行数 | 索引列 | 索引大小估算 | 实际大小范围 |
---|---|---|---|---|
t_personnel_record |
5亿 | (plate, p_id) |
5e8 × (20+8)×1.3 ≈ 18.2GB | 15-25GB |
t_cl_motor |
5亿 | (plate, ctime) |
5e8 × (20+8)×1.3 ≈ 18.2GB | 15-25GB |
总索引空间:约 30-50GB(取决于实际数据分布)
2. 风险分析与规避措施
主要风险:
磁盘空间不足:
- 创建索引需要额外临时空间(≈ 索引大小的1.2倍)
- 解决方案:确保磁盘空闲空间 > 最大表大小的1.5倍
长时锁表(默认CREATE INDEX):
- 阻塞写操作,可能引发应用超时
- 解决方案:使用
CREATE INDEX CONCURRENTLY
内存/CPU过载:
- 排序操作消耗大量
work_mem
- 解决方案:分阶段创建 + 资源控制
- 排序操作消耗大量
3. 安全创建索引方案
步骤1:准备阶段
-- 检查磁盘空间(至少预留100GB)
SELECT pg_size_pretty(pg_tablespace_size('pg_default'));
-- 设置维护内存(加速创建)
SET maintenance_work_mem = '4GB'; -- 不超过总内存25%
步骤2:分阶段并发创建索引
-- 对tr_personnel_record创建索引(不阻塞写入)
CREATE INDEX CONCURRENTLY idx_t_record_plate_pid
ON t_personnel_record (plate, p_id);
-- 对t_clkk_motor创建索引(隔天执行)
CREATE INDEX CONCURRENTLY idx_cl_motor_plate
ON t_cl_motor (plate);
耗时预估(基于 SSD 磁盘):
- 单表索引创建:5亿行 ≈ 2-4小时
- 并发模式速度降低30%,但保证业务连续性
4. 分区表特别优化
方案A:仅索引热分区
-- 只为最近分区创建索引
CREATE INDEX idx_t_record_2025_plate ON t_personnel_record_2025 (plate);
CREATE INDEX idx_cl_motor_2025_plate ON t_cl_motor_2025 (plate);
方案B:使用部分索引
-- 只索引非空数据(减少30%大小)
CREATE INDEX idx_tr_record_active
ON t_personnel_record (plate)
WHERE p_id IS NOT NULL;
5. 监控与应急措施
实时监控命令:
-- 查看索引创建进度
SELECT
pid,
query,
pg_size_pretty(pg_total_relation_size(relid)) AS size
FROM pg_stat_progress_create_index;
-- 监控锁等待
SELECT * FROM pg_locks WHERE mode = 'ShareUpdateExclusiveLock';
应急终止:
-- 终止索引创建
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE query LIKE '%CREATE INDEX%';
6. 存储优化技巧
索引压缩:
CREATE INDEX ... WITH (compression = on); -- PG 14+
- 节省20-40%空间
表空间分离:
CREATE TABLESPACE index_ssd LOCATION '/ssd_data'; CREATE INDEX ... TABLESPACE index_ssd;
清理旧索引:
DROP INDEX IF EXISTS old_index; -- 创建前删除无用索引
7. 最终推荐方案
# 操作流程
1. 申请维护窗口(业务低峰期)
2. 检查磁盘空间:确保 > 100GB 空闲
3. 设置参数:SET maintenance_work_mem='4GB';
4. 创建索引(并发模式):
CREATE INDEX CONCURRENTLY ...;
5. 验证索引:
\d+ t_personnel_record
6. 收集统计信息:
ANALYZE t_personnel_record;
性能影响对比
场景 | CPU峰值 | 磁盘IO | 耗时 | 业务影响 |
---|---|---|---|---|
并发创建索引 | 70% | 高 | 4小时 | 只读延迟 |
标准创建索引 | 100% | 极高 | 1.5小时 | 阻塞写入 |
不创建索引 | - | - | - | 查询超时 |
结论:虽然大表索引会消耗资源,但合理操作不会导致崩溃。建议:
- 使用
CONCURRENTLY
模式- 优先索引热分区
- 预留足够磁盘空间
- 在维护窗口操作
通过此方案,可在保证数据库稳定的前提下,为5亿级分区表安全创建索引。