# 第 16 章 配套代码

本章演示 **声明式分区**（RANGE / HASH / LIST）、**分区裁剪**、**pg_partman 自动维护**、**postgres_fdw 跨库查询**等核心特性。所有自建表都加了 `ch16_` 前缀，避免和其他章节的 `orders / events` 等同名表打架。

## 准备工作

1. 跑一次 init.sql 初始化父表与分区子表：

   ```bash
   psql -h 127.0.0.1 -U postgres -d learn_pg -f ../init.sql
   ```

   会创建 `ch16_orders`（按月 RANGE 分区）、`ch16_events`（HASH 分区）、`ch16_countries`（LIST 分区）等基础测试表。

2. 安装 Python 客户端：

   ```bash
   pip install "psycopg[binary]>=3.1"
   ```

3. （可选）通过环境变量覆盖默认连接：

   ```bash
   export PG_DSN="host=127.0.0.1 port=5432 dbname=learn_pg user=postgres password=postgres"
   ```

4. **05_postgres_fdw.py** 需要可达的「远端」库（脚本里默认用本地的 `learn_pg_archive` 当远端，跑前先 `createdb learn_pg_archive`）。

## 脚本一览（推荐运行顺序）

| 脚本 | 一句话说明 | 关键 PG 特性 |
|------|------------|--------------|
| `01_range_partition_demo.py` | 按月 RANGE 建 `ch16_demo_orders`，演示路由、裁剪、DETACH CONCURRENTLY | `PARTITION BY RANGE`、default 分区、`pg_inherits` |
| `02_hash_partition_demo.py` | 8 个 HASH 分区灌 10 万行，验证分布均匀性与裁剪行为 | `PARTITION BY HASH`、点查裁剪、范围查询无法裁剪 |
| `03_partition_pruning.py` | 用 EXPLAIN 对比裁剪成功/失败 6 种 SQL 写法 | `enable_partition_pruning`、`partitionwise_join`、prepare 计划缓存 |
| `04_partman_simulation.py` | 没装 pg_partman 也能跑，纯 Python 模拟自动建分区 + 滚动归档 | `ch16_my_partman_config`、`ch16_ts_logs` 时序表 |
| `05_postgres_fdw.py` | 用 postgres_fdw 把冷数据归档到「远端」，演示 `Remote SQL` 下推 | `CREATE SERVER`、`CREATE USER MAPPING`、外部表 + 分区结合 |

## 预期输出（节选 03）

```
======================================================================
  场景 A：等值查询（裁剪到 1 个分区）
======================================================================
  Append  (cost=0.00..xx rows=xx width=xx)
    ->  Seq Scan on ch16_orders_2025_03  ...
  ✓ 只扫到 1 个分区
```

## 常见报错与依赖

- `connection refused` → PG 未启动，或 `PG_DSN` 端口写错。
- `relation "ch16_orders" does not exist` → 没跑 `../init.sql`。
- `permission denied to create extension "postgres_fdw"` → 05 脚本需要超级用户，或预先 `CREATE EXTENSION postgres_fdw;`。
- `cannot drop partition ... because other objects depend on it` → 子分区上有外键 / 视图引用，DETACH 前先解依赖。
- pg_partman 真要用得 `CREATE EXTENSION pg_partman;`，本章 04 是模拟实现，不依赖该扩展。
