> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-fbfa8bee.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> 此引擎允许你将 Keeper/ZooKeeper 集群用作具备线性化写入和顺序一致性读取能力的一致性键值存储。

# KeeperMap 表引擎

此引擎允许你将 Keeper/ZooKeeper 集群用作具备线性化写入和顺序一致性读取能力的一致性键值存储。

要启用 KeeperMap 存储引擎，你需要通过 `<keeper_map_path_prefix>` 配置定义一个 ZooKeeper 路径，用于存储这些表。

例如：

```xml theme={null}
<clickhouse>
    <keeper_map_path_prefix>/keeper_map_tables</keeper_map_path_prefix>
</clickhouse>
```

其中，path 可以是任何其他有效的 ZooKeeper 路径。

<div id="creating-a-table">
  ## 创建表
</div>

```sql theme={null}
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
    ...
) ENGINE = KeeperMap(root_path, [keys_limit]) PRIMARY KEY(primary_key_name)
```

引擎参数：

* `root_path` - 存储 `table_name` 的 ZooKeeper 路径。
  该路径不应包含 `<keeper_map_path_prefix>` config 中定义的前缀，因为该前缀会自动追加到 `root_path`。
  此外，还支持 `auxiliary_zookeeper_cluster_name:/some/path` 格式，其中 `auxiliary_zookeeper_cluster` 是在 `<auxiliary_zookeepers>` config 中定义的 ZooKeeper 集群。
  默认情况下，使用在 `<zookeeper>` config 中定义的 ZooKeeper 集群。
* `keys_limit` - 表中允许的键数量。
  这是一个软限制，因此在某些边界情况下，表中的键数量仍可能超过该限制。
* `primary_key_name` – 列列表中的任意列名。
* 必须指定 `primary key`，且主键只支持一列。主键会以二进制形式序列化为 ZooKeeper 中的 `node name`。
* 除主键外的列会按相应顺序序列化为二进制，并作为由序列化键确定的结果节点的值存储。
* 对键使用 `equals` 或 `in` 过滤器的查询会优化为从 `Keeper` 进行多键查找，否则将拉取所有值。

示例：

```sql theme={null}
CREATE TABLE keeper_map_table
(
    `key` String,
    `v1` UInt32,
    `v2` String,
    `v3` Float32
)
ENGINE = KeeperMap('/keeper_map_table', 4)
PRIMARY KEY key
```

使用

```xml theme={null}
<clickhouse>
    <keeper_map_path_prefix>/keeper_map_tables</keeper_map_path_prefix>
</clickhouse>
```

每个值都是 `(v1, v2, v3)` 的二进制序列化结果，并存储在 `Keeper` 中的 `/keeper_map_tables/keeper_map_table/data/serialized_key` 下。
此外，键的数量设有 4 个键的软限制。

如果多个表是在同一个 ZooKeeper 路径上创建的，那么只要至少还有 1 个表在使用该路径，这些值就会持续保留。
因此，在创建表时可以使用 `ON CLUSTER` 子句，以便在多个 ClickHouse 实例之间共享数据。
当然，也可以在彼此无关的 ClickHouse 实例上使用相同的路径手动运行 `CREATE TABLE`，从而实现相同的数据共享效果。

<div id="supported-operations">
  ## 支持的操作
</div>

<div id="inserts">
  ### 插入
</div>

向 `KeeperMap` 插入新行时，如果键不存在，则会为该键创建新条目。
如果键已存在，且设置 `keeper_map_strict_mode` 为 `true`，则会抛出异常；否则，该键对应的值会被覆盖。

示例：

```sql theme={null}
INSERT INTO keeper_map_table VALUES ('some key', 1, 'value', 3.2);
```

<div id="deletes">
  ### 删除
</div>

可以使用 `DELETE` 查询或 `TRUNCATE` 删除行。
如果键存在，且设置 `keeper_map_strict_mode` 为 `true`，则只有在操作能够以原子方式执行时，拉取和删除数据才会成功。

```sql theme={null}
DELETE FROM keeper_map_table WHERE key LIKE 'some%' AND v1 > 1;
```

```sql theme={null}
ALTER TABLE keeper_map_table DELETE WHERE key LIKE 'some%' AND v1 > 1;
```

```sql theme={null}
TRUNCATE TABLE keeper_map_table;
```

<div id="updates">
  ### 更新
</div>

可以使用 `ALTER TABLE` 查询更新值。主键不能更新。
如果将 `keeper_map_strict_mode` 设置为 `true`，则只有以原子方式执行时，拉取和更新数据才会成功。

```sql theme={null}
ALTER TABLE keeper_map_table UPDATE v1 = v1 * 10 + 2 WHERE key LIKE 'some%' AND v3 > 3.1;
```

<div id="related-content">
  ## 相关内容
</div>

* 博客：[使用 ClickHouse 和 Hex 构建实时分析应用](https://clickhouse.com/blog/building-real-time-applications-with-clickhouse-and-hex-notebook-keeper-engine)
