> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blockdb.chaintable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 数据模型

> 了解 BlockDB 的普通表、Block State 表、Block Event 表与 Time 表，以及影子表机制。

# 数据模型

BlockDB 提供三类逻辑表：**普通表**，以及业务抽象层的 **Block State 表**、**Block Event 表** 与 **Time 表**。它们面向不同的数据形态，服务于不同的业务场景。

## 三类逻辑表概览

| 逻辑表 | 数据形态 | 典型业务场景 |
| - | - | - |
| 普通表（Table） | 行级 | 非链上业务数据、加工后的高价值数据 |
| Block State 表 | 链上状态，随高度变化 | 代币余额、合约状态、NFT 持有人 |
| Block Event 表 | 链上事件，按区块粒度追加或替换 | 代币转账（token\_transfer）、合约事件 |
| Time 表 | 物理时间序列 | token 的美元价格、TVL 快照 |

## 普通表（Table）

普通表直接对应一张物理在线表（1:1），用于存储非链上的业务数据，或链上数据处理后的高价值数据。它提供行级、语义化的读写与扫描 API。

```python theme={null}
from blockdb import Table

# 普通在线表：建表走平台页面，SDK 不开放 Meta
rules = Table("demo.rules")

# 写：upsert_rows 实时写
rules.upsert_rows([
    {"id": "rule_1", "name": "min_value", "threshold": 100},
    {"id": "rule_2", "name": "max_value", "threshold": 999},
])

# 读：按主键 / 批量 / 全表扫描
print(rules.get_row("rule_1"))
print(rules.batch_get_rows(["rule_1", "rule_2"]))
rows = rules.scan("SELECT * FROM demo.rules")
```

## Block State 表

**作用**：维护链上实体的最新状态，以及任意历史高度的状态。每当新高度的数据进入，BlockDB 会保存该高度的历史快照，并异步更新最新状态表。

**业务场景示例**：

* 用户地址的代币余额（Balance）。
* 智能合约的当前状态变量。
* NFT 的当前持有人。

例如，你可以查询"地址 `0xabc...` 在区块高度 `18000000` 时的 USDC 余额"——Block State 表能按区块时刻返回任意历史高度的状态。

## Block Event 表

**作用**：维护链上发生的每一条事件，例如 `token_transfer` 转账事件。事件在特定高度发生后就是唯一、不可变的，只有追加，没有更新。

**业务场景示例**：

* 代币转账流水（token\_transfer）。
* 合约抛出的事件。
* 交易所的每笔撮合记录。

例如，订阅某 token 的 `transfer` 事件，即可实时统计每一笔转账的 `from` / `to` / `value`。

## Time 表

**作用**：维护某对象随现实世界（物理挂钟）时间变化的状态序列，例如 token 的美元价格表。

**业务场景示例**：

* token 每分钟的美元价格。
* 每分钟的 TVL 快照。
* 任何随物理时间变化的指标。

例如，你可以保存 USDC 每分钟的美元价格，并随时按时间戳查询历史价格。

***

Block State 表与 Block Event 表的模型与链上语义详见 [Block State 与 Block Event 表](/zh/concepts/block-tables)；Time 表详见 [Time 表](/zh/concepts/time-table)。

## 影子表机制

业务抽象表本身不直接对应一张物理表。创建一张业务抽象表时，BlockDB 会自动在存储层创建多张协作的普通表（影子表），按职责分离维护不同维度的数据：

| 业务抽象表 | 派生的影子表 | 职责 |
| - | - | - |
| **Block State 表** | 主表<br />`_archive`<br />`_height`<br />`_bundle` | 最新值<br />历史高度快照<br />处理进度 / 共识高度<br />数据区间 hash |
| **Block Event 表** | 主表<br />`_height`<br />`_bundle` | 原始事件（只追加，不维护 `_archive`）<br />处理进度 / 共识高度<br />数据区间 hash |
| **Time 表** | 主表<br />`_archive` | 最新桶<br />历史（复合主键 `(id, time_at)`） |

<Note>
  子表名使用**下划线**前缀：`<业务抽象名>._archive` / `_height` / `_bundle`。
</Note>

* **`_height` 表**：记录 `height_start` / `height_end` 闭区间，标识哪些高度区间已被连续处理，也用于判断共识高度。排查数据是否断档时使用，写代码几乎用不到。
* **`_archive` 表**：保存历史快照。与源表结构一致，但 `id` 字段变为 `original_id`，并新增新的 `id` 字段。
* **`_bundle` 表**：维护每 1000 个 block 的数据 hash，主要供 S3 同步等离线系统使用。

派生表可以通过普通表的读取 API（`GetRow` / `BatchGetRows` / `FilterRows`）直接访问，方便排查数据或做专业模式读取。但**禁止使用普通表写入 API 直接修改派生表**——所有写入必须通过业务抽象表自身的区块 / 时间语义写接口完成。

### Block State 影子表示意

<img src="https://mintcdn.com/block-db/M4RlWXbYqfjMAmjc/images/image.png?fit=max&auto=format&n=M4RlWXbYqfjMAmjc&q=85&s=863a8d2d2a9b388fd341de446947595b" alt="Block State 影子表" width="856" height="118" data-path="images/image.png" />

### Block Event 影子表示意

<img src="https://mintcdn.com/block-db/M4RlWXbYqfjMAmjc/images/image-1.png?fit=max&auto=format&n=M4RlWXbYqfjMAmjc&q=85&s=8c9aa283422b56d7c78b4b0f3e85a1df" alt="Block Event 影子表" width="772" height="90" data-path="images/image-1.png" />

### \_height 进度表示意

<img src="https://mintcdn.com/block-db/M4RlWXbYqfjMAmjc/images/image-2.png?fit=max&auto=format&n=M4RlWXbYqfjMAmjc&q=85&s=77849bdd418265fa4b4de97e1fe7cab4" alt="_height 进度表" width="842" height="196" data-path="images/image-2.png" />


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.