文档修改
This commit is contained in:
@@ -762,15 +762,64 @@ class PropertyManager(ActiveManager):
|
||||
## 八、数据量与性能预测
|
||||
|
||||
| 表名 | 预估行数 | 增长速度 | 分区策略 |
|
||||
|------|---------|---------|---------|
|
||||
|------|---------|---------|---------|
|
||||
| `properties` | 89,000+ | 中速 | 暂不分区,建议 500k 后按 `created_at` RANGE 分区 |
|
||||
| `follow_logs` | 200万+ | 高速(最高频写入) | 按 `created_at` 月度 RANGE 分区 |
|
||||
| `property_photos` | 500万+ | 高速 | 按 `property_id` HASH 分区(16分区) |
|
||||
| `follow_logs` | 200万+ | 高速(最高频写入) | ✅ `PARTITION BY RANGE (created_at)` 月度分区 |
|
||||
| `property_photos` | 500万+ | 高速 | ✅ `PARTITION BY RANGE (created_at)` 月度分区 |
|
||||
| `permission_change_logs` | 100万+ | 中高速 | ✅ `PARTITION BY RANGE (operated_at)` 月度分区 |
|
||||
| `login_attempts` | 500万+ | 高速(每次登录一条) | ✅ `PARTITION BY RANGE (attempted_at)` 月度分区 |
|
||||
| `platform_audit_logs` | 10万+ | 低中速 | ✅ `PARTITION BY RANGE (created_at)` 月度分区 |
|
||||
| `price_changes` | 50万 | 中速 | 无需分区 |
|
||||
| `listing_histories` | 20万 | 低速 | 无需分区 |
|
||||
| `clients` | 10万+ | 中速 | 暂不分区 |
|
||||
| `viewings` | 100万 | 中速 | 无需分区 |
|
||||
|
||||
### 8.1 分区维护策略(partition_maintenance_task)
|
||||
|
||||
所有月度分区表统一由 **Celery Beat 定时任务** `partition_maintenance_task` 维护,每月 1 日凌晨 01:00(UTC+8)自动执行:
|
||||
|
||||
```python
|
||||
# apps/property/tasks.py(及 permission/login/shared 各 App 对应任务)
|
||||
@app.task(name="partition_maintenance_task")
|
||||
def partition_maintenance_task():
|
||||
"""
|
||||
为下一个月预建所有分区表的分区。
|
||||
- 检查是否已存在目标分区,幂等执行
|
||||
- 失败时发送 Sentry 告警
|
||||
"""
|
||||
tables = [
|
||||
("follow_logs", "created_at"),
|
||||
("property_photos", "created_at"),
|
||||
("permission_change_logs", "operated_at"),
|
||||
("login_attempts", "attempted_at"),
|
||||
("public.platform_audit_logs", "created_at"),
|
||||
]
|
||||
next_month = date.today().replace(day=1) + relativedelta(months=1)
|
||||
month_start = next_month
|
||||
month_end = next_month + relativedelta(months=1)
|
||||
|
||||
for table, _key in tables:
|
||||
suffix = month_start.strftime("%Y_%m")
|
||||
part_name = f"{table.replace('.', '_')}_{suffix}"
|
||||
sql = f"""
|
||||
CREATE TABLE IF NOT EXISTS {part_name}
|
||||
PARTITION OF {table}
|
||||
FOR VALUES FROM ('{month_start}') TO ('{month_end}');
|
||||
"""
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(sql)
|
||||
```
|
||||
|
||||
**Celery Beat 配置**(`celery.py`):
|
||||
```python
|
||||
app.conf.beat_schedule["partition_maintenance_task"] = {
|
||||
"task": "partition_maintenance_task",
|
||||
"schedule": crontab(day_of_month=1, hour=1, minute=0), # 每月1日 01:00 UTC+8
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ **注意**:每张分区表均保留一个 `_default` 默认分区作为兜底,防止任务失败时写入报错。`_default` 分区数据应在运维 SOP 中周期性检查(有数据则说明提前建分区失败)。
|
||||
|
||||
---
|
||||
|
||||
## 九、必须在开发启动前明确的数据架构决策
|
||||
|
||||
Reference in New Issue
Block a user