---
title: ClickHouse 视图通道
description: 宿主在自有 ClickHouse 数仓建只读视图,PAC 直接 SQL 拉取的存量加增量统一通道。
icon: Database
---

> **一句话**:宿主在自己的 ClickHouse 数仓里建一组只读视图(每类业务一张),PAC 直接 SQL 拉,**存量 + 增量同一通道**,宿主不用写任何 REST 接口。
>
> **适用对象**:数据已经在 CH 数仓里(典型 = 集团 DW 已经 ETL 过来),不想为 PAC 单独建一套接入 endpoint 的宿主。
>
> **状态**:Pull **三种数据源之一**(文件 / CH 直连 / REST);跟其它源**契约和数据字典完全互通**,切换零返工。

---

## 1. 跟现有通道的关系

| 通道 | 数据形态 | 增量机制 | 宿主侧工作 |
|---|---|---|---|
| Cold-import | CSV/JSON dump | ❌ 一次性 | `SELECT *` 导出 |
| Pull (REST) | HTTP JSON | 游标查询参数 | 实现 14 个 REST endpoint |
| Push | HTTP JSON | 实时事件 | 主动推 + HMAC |
| **CH 视图(本文档)** | **CH 行** | **视图内单调列 + SQL `WHERE`** | **建视图 + 给只读账号** |

**核心理念**:CH 视图 = REST Pull 的 SQL 变体 —— 把 HTTP 换成直连 SQL,游标语义、数据字典、容错保障**全部复用**(对宿主完全一致)。

**存量 + 增量同一条**:首次跑 `WHERE updated_at > 0` 拿全量,之后每次跑 `WHERE updated_at > <上次游标>` 拿增量,**不用再做 cold-import 一次性 dump**。

---

## 2. 宿主要做什么(4 步,工作量约 1-2 天)

### 2.1 建视图(每类业务一张,共 7 张必填 + 7 张可选)

视图名建议 `dw.v_pac_<resource>`,字段命名 / 嵌套 / 枚举编码**宿主自由**——PAC 侧 yaml 映射,跟 pull / cold-import 共用同一份[数据字典](/docs/integration/data-request-checklist)。

| 视图名(建议)| 必/选 | 对应业务 |
|---|---|---|
| `dw.v_pac_patients` | 🔴 必 | 患者主档 |
| `dw.v_pac_appointments` | 🔴 必 | 预约 |
| `dw.v_pac_clinical_encounters` | 🔴 必 | 接诊 |
| `dw.v_pac_emr_documents` | 🔴 必 | 电子病历 ⭐ |
| `dw.v_pac_image_studies` | 🔴 必 | 影像 metadata ⭐ |
| `dw.v_pac_orders` | 🔴 必 | 收费单 / 医嘱 |
| `dw.v_pac_payments` | 🔴 必 | 收款 |
| `dw.v_pac_recharges` | 🟠 强烈推荐 | 充值 / 储值 |
| `dw.v_pac_complaints` | 🟠 强烈推荐 | 投诉 |
| `dw.v_pac_referrals` | 🟠 强烈推荐 | 转介绍 |
| `dw.v_pac_refunds` / `consultations` / `visit_registrations` / `visit_receptions` | 🟡 可选 | — |

### 2.2 每张视图必须含「必带列」

视图 SELECT 里要带上[每张表必带的列](/docs/integration/data-request-checklist)(主键 / 患者外键 / 诊所 / 命名空间 / 单调更新列),并按约定的试点诊所过滤:

```sql
-- 示例:dw.v_pac_clinical_encounters
CREATE VIEW dw.v_pac_clinical_encounters AS
SELECT
  enc_id,                          -- 业务主键(幂等锚)
  clinic_id,                       -- 诊所
  patient_id,                      -- 患者外键
  brand,                           -- 命名空间(多品牌必带 → source_unit)
  -- ...所有业务字段原样...,
  etl_updated_at                   -- 单调递增列(游标基准,必须随每次行变更递增)
FROM dw.dwd_encounter_main
WHERE clinic_id IN ('clinic_a', 'clinic_b' /* ... */);  -- 按约定的试点诊所过滤
```

> 单调递增列(`etl_updated_at` / `_version` / 时间戳)是 CH 通道做增量游标的关键 —— 没有就只能全表扫。

**关于 1:N 子表**(如接诊主表 + 诊断 / 治疗子表)——两种处理都行:
- **方案 A(推荐)**:在视图里用 CH 的 `groupArray` / `arrayMap` 聚成嵌套 JSON 字段,一行 = 完整业务对象
- **方案 B**:子表也建独立视图,PAC 侧 join

### 2.3 开只读账号 + 网络打通

```sql
CREATE USER pac_reader IDENTIFIED BY '<32位强随机>';
GRANT SELECT ON dw.v_pac_* TO pac_reader;
-- 不需要任何 INSERT / ALTER / 表级权限
```

**网络可达性**(三选一,按宿主合规要求):
- VPN / 内网专线(推荐)
- CH HTTPS 端口 + IP 白名单(把 PAC 出口 IP 报给宿主)
- 跳板 / 反代

⚠️ **公网直连 CH Native 协议(9000)合规雷区**——必走加密通道。

### 2.4 提供数据字典

跟 pull / cold-import 共用同一份,见 [数据请求清单](/docs/integration/data-request-checklist) §3。
**枚举值含义必须列全**——`status='02'` 是"完成"还是"作废",字典没写 PAC 只能猜。

---

## 3. PAC 怎么用这些视图(宿主了解即可,不用做)

PAC 按配置间隔(默认 5 分钟)轮询每张视图,用单调列做增量游标:

```sql
SELECT * FROM dw.v_pac_clinical_encounters
WHERE etl_updated_at > {上次游标}
ORDER BY etl_updated_at, enc_id     -- 双列排序防同毫秒漏数
LIMIT 200;
```

首次全量(游标从 0 起)→ 之后只取 `etl_updated_at` 变大的行;客服点"刷新"时按 `patient_id` 即时查该患者当前态。幂等去重、断点续传、每日对账、字段漂移告警等容错全在 PAC 侧,宿主不用管。

> 增量游标 / 响应语义 / 错误处理与 [REST API 通道](/docs/integration/channel-rest) 完全一致,只是承载从 HTTP 换成 SQL。

---

## 4. 跟 REST Pull / Cold-import 的取舍

| 维度 | CH 视图 | REST Pull | Cold-import |
|---|---|---|---|
| 宿主工作量 | ⭐⭐⭐ 建视图 + 开账号(1-2 d)| ⭐ 写 14 个 endpoint(3-5 d)| ⭐⭐ 一次 dump(0.5 d)|
| 实时性 | 视图刷新频率(典型小时级)| 准实时(5 min) | ❌ 不支持增量 |
| 存量 + 增量统一 | ✅ 同一条 | ❌ 需配合 cold-import | ❌ 只解决存量 |
| 字段稳定性 | ⚠️ 视图列改 PAC SQL 立刻挂(需 2 周通知)| ✅ 接口契约稳 | n/a |
| 网络 | ⚠️ 需 VPN / 内网 | ✅ HTTPS 即可 | ✅ 文件传输 |
| 5 诊所历史回灌 | ✅ SQL 一把扫 30 min | ❌ 翻页慢 | ✅ |
| 适合场景 | **DW 数仓已就位** | 业务系统直出 | 临时 / 一次性 |

**典型选择**:
- 集团 DW 已经把宿主数据 ETL 到 CH → **走 CH 视图**(最低成本)
- 宿主只有 OLTP 没数仓 → **走 REST Pull**
- 两边都搞不定先上线 → **走 Cold-import** 兜底,后面补正

---

## 5. 接入 Checklist(宿主自查)

### 必填
- [ ] 7 张必填视图建好,字段命名按宿主习惯即可
- [ ] 每张视图含[必带列](/docs/integration/data-request-checklist)(主键 / 患者外键 / 诊所 / 命名空间 / 单调更新列)
- [ ] 视图已按约定的试点诊所过滤
- [ ] `pac_reader` 只读账号建好,密码用强随机,plaintext 一次性交付 PAC
- [ ] 网络可达性方案确定(VPN / 白名单 / 跳板)并完成测试
- [ ] 数据字典交付(参考 [数据字典示例](/docs/integration/data-dictionary))
- [ ] **视图刷新频率写明**(5 min / 1 h / T+1?)
- [ ] **字段变更 SLA**:提前 2 周通知 PAC

### 强烈推荐
- [ ] 3 张推荐视图(`recharges` / `complaints` / `referrals`)
- [ ] 1:N 子表已聚成嵌套 JSON 列(避免 PAC 侧多次查询)
- [ ] 视图查询性能验证:`WHERE etl_updated_at > now() - INTERVAL 1 HOUR LIMIT 200` 应 `< 1 s`

### 可选
- [ ] 4 张可选视图
- [ ] [actionUrls](/docs/integration/overview) 模板(deep-link 跳回宿主 UI)

---

## 6. 跟宿主对齐时的 5 个必问问题

不管前面文档读没读,直接拉对方在群里答这 5 个:

1. **视图里有没有单调递增列**(`etl_updated_at` / `_version` / 时间戳)?名字是啥?
2. **视图多久刷一次**?实时 / 5 min / 1 h / T+1?
3. **PAC 服务器怎么连你 CH 集群**?VPN / 内网专线 / 公网+白名单?哪种走得通?
4. **视图字段稳定性**——你们改表 / 改 ETL 时能提前多久通知 PAC?
5. **视图是否已经按诊所过滤**?试点 clinic_id 是哪些?

5 个对齐了就可以开工。

---

## 7. 不在本通道范围的事

CH 视图只替换"数据接入"那一段;鉴权换票 / iframe 嵌入 / actionUrls 是独立链路(跟选哪种通道无关),见 [数据请求清单 §8](/docs/integration/data-request-checklist)。

---

**联系**:对接细节 / 视图字段含义 / 性能问题,找 PAC 接入对接人。
