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

# SeaweedFS 目录

> 本指南将逐步介绍如何使用 ClickHouse 和 SeaweedFS Iceberg 目录查询数据。

export const ExperimentalBadge = () => {
  return <a href="https://clickhouse.com/docs/reference/settings/beta-and-experimental-features#experimental-features" className="experimentalBadge">
            <div className="experimentalIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.25" d="M5.5 2H10.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M9.50015 2V6.19625L13.4283 12.7425C13.4738 12.8183 13.4985 12.9049 13.4996 12.9934C13.5008 13.0818 13.4785 13.169 13.435 13.246C13.3914 13.323 13.3283 13.3871 13.2519 13.4317C13.1755 13.4764 13.0886 13.4999 13.0002 13.5H3.00015C2.91164 13.5 2.8247 13.4766 2.74822 13.432C2.67174 13.3874 2.60847 13.3233 2.56487 13.2463C2.52126 13.1693 2.49889 13.082 2.50004 12.9935C2.50119 12.905 2.52582 12.8184 2.5714 12.7425L6.50015 6.19625V2" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M4.47656 9.56754C5.30344 9.41254 6.47656 9.47942 7.99969 10.25C10.0153 11.2707 11.4216 11.0569 12.2184 10.7282" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            Experimental 功能
        </a>;
};

<ExperimentalBadge />

<Note>
  SeaweedFS 目录集成仅适用于 Iceberg 表。
</Note>

ClickHouse 支持集成多个目录 (Unity、Glue、REST、Polaris 等) 。本指南将介绍如何使用 ClickHouse 和 [SeaweedFS](https://github.com/seaweedfs/seaweedfs) 目录查询数据。

SeaweedFS 是开源的分布式文件和对象存储，提供兼容 S3 的网关。其 S3 Table Buckets 同时提供 Iceberg 部署所需的两个组件：内嵌的 Iceberg REST 目录提供表元数据，存储桶则通过同一 S3 端点以 Parquet 文件形式存储表数据：

* **单一服务** - 目录元数据和 Parquet 数据均由同一进程提供，无需单独的元数据数据库
* **REST API** - 符合 Iceberg REST 目录规范
* **服务端维护** - 自动执行 Parquet 合并整理和快照过期处理，无需外部维护服务

<Note>
  由于此功能仍处于实验阶段，您需要使用以下命令启用它：
  `SET allow_experimental_database_iceberg = 1;`
</Note>

<div id="local-development-setup">
  ## 本地开发环境搭建
</div>

对于本地开发和测试，您可以使用 Docker Compose 运行 SeaweedFS 和 ClickHouse。这种方式非常适合学习、原型开发和开发环境。

<div id="local-prerequisites">
  ### 前置条件
</div>

1. **Docker 和 Docker Compose**：确保已安装并运行 Docker
2. **版本**：SeaweedFS 4.42 或更高版本；ClickHouse 26.8 或更高版本 (25.8 及之后的版本可以读取和插入数据，但通过目录创建表需要 26.8)
3. **安装了 PyIceberg 的 Python** (可选) ：用于在下文中填充样本数据

<div id="setting-up-local-seaweedfs-catalog">
  ### 设置本地 SeaweedFS 目录
</div>

\*\*第 1 步：\*\*创建一个新文件夹以运行示例，然后创建包含 S3 网关和目录凭据的 `s3config.json` 文件：

```json theme={null}
{
  "identities": [
    {
      "name": "analyst",
      "credentials": [
        {
          "accessKey": "tutorialkey",
          "secretKey": "tutorialsecret"
        }
      ],
      "actions": ["Admin", "Read", "Write", "List", "Tagging"]
    }
  ]
}
```

\*\*第 2 步：\*\*创建 `docker-compose.yml` 文件，并添加以下配置：

```yaml theme={null}
services:
  seaweedfs:
    image: chrislusf/seaweedfs:latest
    command: mini -dir=/data -s3.config=/etc/seaweedfs/s3config.json -tableBucket=analytics
    ports:
      - "8333:8333"   # S3 endpoint
      - "8181:8181"   # Iceberg REST catalog
    volumes:
      - ./s3config.json:/etc/seaweedfs/s3config.json
      - seaweedfs_data:/data
    networks:
      - iceberg_net

  clickhouse:
    image: clickhouse/clickhouse-server:latest
    container_name: seaweedfs-clickhouse
    ports:
      - "8123:8123"
      - "9000:9000"
    depends_on:
      - seaweedfs
    networks:
      - iceberg_net

volumes:
  seaweedfs_data:

networks:
  iceberg_net:
    driver: bridge
```

`mini` 命令会在单个容器中启动完整的 SeaweedFS 技术栈。`-tableBucket=analytics` 标志会预先创建一个名为 `analytics` 的 S3 Tables 存储桶，作为 Iceberg 仓库。

\*\*第 3 步：\*\*运行以下命令启动服务：

```bash theme={null}
docker compose up -d
```

<div id="seeding-sample-data">
  ### 写入样本数据
</div>

目录初始为空。使用 PyIceberg (`pip install pyiceberg pyarrow`) 创建一个表，并追加几行数据：

```python theme={null}
import pyarrow as pa
from pyiceberg.catalog.rest import RestCatalog

catalog = RestCatalog(
    "seaweedfs",
    uri="http://localhost:8181",
    warehouse="s3://analytics",
    credential="tutorialkey:tutorialsecret",
    **{
        "s3.endpoint": "http://localhost:8333",
        "s3.access-key-id": "tutorialkey",
        "s3.secret-access-key": "tutorialsecret",
        "s3.region": "us-east-1",
        "s3.path-style-access": "true",
    },
)

rows = pa.table({
    "id": pa.array([1, 2, 3, 4, 5, 6], pa.int64()),
    "region": ["NA", "EU", "EU", "APAC", "NA", "EU"],
    "amount": pa.array([12.5, 40.0, 7.25, 99.9, 3.5, 61.0], pa.float64()),
})

catalog.create_namespace("sales")
table = catalog.create_table("sales.orders", schema=rows.schema)
table.append(rows)
```

<div id="connecting-to-local-seaweedfs-catalog">
  ### 连接到本地 SeaweedFS 目录
</div>

连接到您的 ClickHouse 容器：

```bash theme={null}
docker exec -it seaweedfs-clickhouse clickhouse-client
```

然后创建与 SeaweedFS 目录的数据库连接：

```sql theme={null}
SET allow_experimental_database_iceberg = 1;

CREATE DATABASE lake
ENGINE = DataLakeCatalog('http://seaweedfs:8181/v1', 'tutorialkey', 'tutorialsecret')
SETTINGS catalog_type = 'rest',
    warehouse = 's3://analytics',
    storage_endpoint = 'http://seaweedfs:8333/analytics',
    catalog_credential = 'tutorialkey:tutorialsecret',
    oauth_server_uri = 'http://seaweedfs:8181/v1/oauth/tokens'
```

引擎 参数包含 ClickHouse 读取表数据所需的 S3 凭据；`catalog_credential` 和 `oauth_server_uri` 则通过 OAuth2 客户端凭据流程对目录本身进行身份验证。SeaweedFS 对两者均可使用相同的访问密钥和密钥。

<div id="querying-seaweedfs-catalog-tables-using-clickhouse">
  ## 使用 ClickHouse 查询 SeaweedFS 目录中的表
</div>

连接建立后，您可以开始通过 SeaweedFS 目录查询数据。例如：

```sql theme={null}
USE lake;

SHOW TABLES;
```

```response theme={null}
┌─name─────────┐
│ sales.orders │
└──────────────┘
```

<Info>
  **必须使用反引号**

  必须使用反引号，因为 ClickHouse 不支持多个命名空间。
</Info>

查询表：

```sql theme={null}
SELECT region, sum(amount) AS total
FROM `sales.orders`
GROUP BY region
ORDER BY total DESC;
```

```response theme={null}
┌─region─┬──total─┐
│ EU     │ 108.25 │
│ APAC   │   99.9 │
│ NA     │     16 │
└────────┴────────┘
```

<div id="creating-tables-and-writing-data-from-clickhouse">
  ## 从 ClickHouse 创建表并写入数据
</div>

您还可以在 SeaweedFS 目录中创建表，并直接通过 ClickHouse 向其中写入数据：

```sql theme={null}
SET allow_experimental_database_iceberg = 1;
SET allow_experimental_insert_into_iceberg = 1;
SET write_full_path_in_iceberg_metadata = 1;

CREATE TABLE lake.`sales.returns` (id Int64, reason String)
ENGINE = IcebergS3('http://seaweedfs:8333/analytics/sales/returns/', 'tutorialkey', 'tutorialsecret');

INSERT INTO lake.`sales.returns` VALUES (1, 'damaged'), (2, 'wrong size');

SELECT * FROM lake.`sales.returns` ORDER BY id;
```

```response theme={null}
┌─id─┬─reason─────┐
│  1 │ damaged    │
│  2 │ wrong size │
└────┴────────────┘
```

`IcebergS3` 引擎子句指定新表的存储路径，`write_full_path_in_iceberg_metadata` 使 ClickHouse 将完整的表位置注册到目录中。

<Note>
  通过目录创建表需要 ClickHouse 26.8 或更高版本。26.4 至 26.7 版本会先写入表文件，再注册命名空间；除非该命名空间已存在于目录中，否则 SeaweedFS 会拒绝此操作。早于 26.4 的版本看似成功，但表文件会写入对象存储，而不会注册到目录中。
</Note>

当 ClickHouse 提交插入操作时，SeaweedFS 目录会修复实验性 writer 尚未生成的元数据：补全清单中缺失的字段 ID，将相对于存储桶的文件路径重写为绝对位置，并为表设置默认的名称映射。随后，PyIceberg 和 Spark 等严格 reader 即可读取 ClickHouse 写入的行。这需要 SeaweedFS 4.42 或更高版本。

<div id="loading-data-from-your-data-lake-into-clickhouse">
  ## 将数据从数据湖加载到 ClickHouse
</div>

如需将 SeaweedFS 目录中的数据加载到 ClickHouse，请先创建一个本地 ClickHouse 表：

```sql theme={null}
CREATE TABLE default.orders
(
    `id` Int64,
    `region` String,
    `amount` Float64
)
ENGINE = MergeTree()
ORDER BY (region, id);
```

然后使用 `INSERT INTO SELECT` 将 SeaweedFS 目录表中的数据加载到 ClickHouse：

```sql theme={null}
INSERT INTO default.orders
SELECT * FROM lake.`sales.orders`;
```
