80 lines
2.5 KiB
Python
80 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
数据库维护脚本
|
|
- 不删除任何历史数据
|
|
- 只执行 VACUUM ANALYZE 优化查询性能
|
|
- 统计各表数据量和磁盘占用
|
|
建议通过 crontab 每周日凌晨执行一次
|
|
"""
|
|
import os
|
|
import sys
|
|
import psycopg2
|
|
from datetime import datetime
|
|
|
|
# 数据库配置
|
|
DB_CONFIG = {
|
|
'host': os.environ.get('DB_HOST', 'localhost'),
|
|
'port': int(os.environ.get('DB_PORT', 5432)),
|
|
'database': os.environ.get('DB_NAME', 'stock_app'),
|
|
'user': os.environ.get('DB_USER', 'postgres'),
|
|
'password': os.environ.get('DB_PASSWORD', ''),
|
|
}
|
|
|
|
|
|
def cleanup():
|
|
"""数据库维护:统计数据量 + VACUUM ANALYZE 优化性能"""
|
|
print(f"{'='*60}")
|
|
print(f"[{datetime.now():%Y-%m-%d %H:%M:%S}] 数据库维护开始")
|
|
print(f" 策略:保留全部历史数据,仅执行性能优化")
|
|
print(f"{'='*60}")
|
|
|
|
try:
|
|
conn = psycopg2.connect(**DB_CONFIG)
|
|
conn.autocommit = True
|
|
cur = conn.cursor()
|
|
|
|
# 1. 统计各表数据量
|
|
print(f"\n 📊 各表数据量统计:")
|
|
cur.execute("""
|
|
SELECT relname as table_name,
|
|
n_live_tup as row_count,
|
|
pg_size_pretty(pg_total_relation_size(relid)) as total_size,
|
|
pg_total_relation_size(relid) as raw_size
|
|
FROM pg_catalog.pg_statio_user_tables
|
|
ORDER BY pg_total_relation_size(relid) DESC
|
|
""")
|
|
total_size = 0
|
|
tables = []
|
|
for name, rows, size, raw in cur.fetchall():
|
|
total_size += raw
|
|
tables.append(name)
|
|
print(f" {name:>30}: {rows:>12,} 行 {size:>10}")
|
|
print(f" {'─'*55}")
|
|
print(f" {'总计':>30}: {'':>12} {total_size / 1024 / 1024:.0f} MB")
|
|
|
|
# 2. VACUUM ANALYZE 优化查询性能
|
|
print(f"\n 🔧 VACUUM ANALYZE (更新统计信息,优化查询)...")
|
|
for table in tables:
|
|
try:
|
|
t0 = datetime.now()
|
|
cur.execute(f"VACUUM ANALYZE {table}")
|
|
elapsed = (datetime.now() - t0).total_seconds()
|
|
if elapsed > 1:
|
|
print(f" {table}: {elapsed:.1f}s")
|
|
except Exception as e:
|
|
print(f" {table}: ⚠ {e}")
|
|
|
|
print(f"\n[{datetime.now():%Y-%m-%d %H:%M:%S}] 维护完成 ✅")
|
|
print(f"{'='*60}")
|
|
|
|
cur.close()
|
|
conn.close()
|
|
|
|
except Exception as e:
|
|
print(f"维护失败: {e}")
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
cleanup()
|