Files
order_site/docs/数据库SQL约束与运维.md
T

41 lines
2.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 数据库 SQL 约束与运维
## 提交前约束
新增或修改 SQL 必须满足:
1. 列表查询必须有明确的分页、最大数量或日期范围;禁止无界返回历史数据。
2. `GROUP BY``COUNT(DISTINCT)`、窗口函数和跨表聚合必须附带 `EXPLAIN (ANALYZE, BUFFERS)` 结果。
3. 高频接口禁止在公共 `SELECT` 中叠加未必要的 LATERAL、相关子查询或全表聚合。
4. 当前页关联数据必须按当前页 ID 批量查询,不得读取用户全部历史记录再在应用层过滤。
5. 新增索引必须通过数据库 migration 提交,并说明覆盖的查询条件;大表生产索引应评估锁影响。
6. SQL 必须使用参数绑定,禁止把请求参数直接拼接到 SQL 值中。
后端 `npm run check` 会执行 `npm run check:sql`,检查关键性能防线没有被重构移除。该检查不能替代真实数据量下的 `EXPLAIN`
## 生产观测
生产 PostgreSQL 应启用 `pg_stat_statements` 和慢查询日志。Compose 默认通过 `POSTGRES_LOG_MIN_DURATION_STATEMENT_MS`(默认 500ms)配置 PostgreSQL 原生慢查询日志;应用默认将执行超过 `DATABASE_SLOW_QUERY_THRESHOLD_MS`(默认 500ms)的 SQL 记录为慢查询,只记录 SQL 形状、耗时和返回行数,不记录参数值。
常用排查 SQL
```sql
SELECT calls, total_exec_time, mean_exec_time, rows, query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 30;
SELECT pid, state, wait_event_type, wait_event,
now() - query_start AS duration, query
FROM pg_stat_activity
WHERE datname = current_database() AND state <> 'idle'
ORDER BY query_start;
```
## 容量边界
- `DATABASE_STATEMENT_TIMEOUT_MS` 防止单条 SQL 长时间占用连接。
- `DATABASE_MAX_CONNECTIONS` 按后端实例数总量评估;扩容后端实例时不能简单地每实例增加连接数。
- CPU 限额只能防止数据库拖垮整机,不能替代 SQL 优化。
- 数据量持续增长后,排行榜和历史统计应迁移到汇总表、缓存或只读副本,不应继续依赖在线全量聚合。