Remote 和 RemoteSecure 数据库引擎可通过原生 TCP 协议实时访问远程 ClickHouse 服务器上某个数据库中的表。它们相当于 ClickHouse 到 ClickHouse 场景下的 MySQL 和 PostgreSQL 数据库引擎。
表列表及其结构会按需从远程服务器拉取 (底层使用 SHOW TABLES 和 DESCRIBE TABLE) ,因此该数据库始终反映远程服务器的当前状态。每个表都会以 Distributed 存储的形式提供,该存储基于所提供的地址构建临时集群,并将 SELECT 和 INSERT 查询转发至远程服务器。
这对于联合多个 ClickHouse 集群,或将较大的 ClickHouse 集群接入 clickhouse-local 或较小的集群非常方便。
创建数据库
- Remote
- RemoteSecure
如果省略端口,
Remote 将通过普通 TCP 端口连接 (tcp_port,默认值为 9000) 。addresses_expr— 远程服务器地址,或用于生成多个地址的表达式,格式为host或host:port。地址表达式支持与remote表函数相同的 glob 模式 (例如{a,b,c}、{N..M}和{a|b},可展开为多个分片和副本) 。如果省略端口,Remote使用普通 TCP 端口 (tcp_port,默认值为9000) ,RemoteSecure使用安全 TCP 端口 (tcp_port_secure,默认值为9440) 。database— 远程服务器上的数据库名称。user— 远程用户名。可选,默认值:default。password— 远程用户密码。可选,默认值:空。
SHOW CREATE DATABASE 会隐藏密码。与 remote 表函数一样,指向当前服务器的地址会被视为本地分片:SELECT 和 INSERT 会直接以当前用户身份执行,因此该用户必须拥有底层数据库及其表的相应特权;存储的凭据仅用于真正的远程服务器。如果某个分片的本地副本没有该数据库或表,查找将像 Distributed 表一样回退到该分片的远程副本。在这种情况下,SHOW CREATE TABLE 输出的是实际生效的回退地址 (从各分片中剔除本地副本) ,而非配置的地址,因此生成的 Remote(...) 表定义能够重建实际处理查询的对象。
当地址表达式描述多个分片时,每个代理表都会从所有分片读取,但元数据——表列表及其结构——与 remote 表函数一样,取自任意一个分片 (优先本地分片) ,这样列出表只需执行一次查询,而不是每个分片执行一次。因此,集群中的各分片应提供相同的一组表;如果某张表仅存在于部分分片上,对该表的代理查询会在没有该表的分片上失败。向多分片数据库中的表执行 INSERT 时,每一行都会被发送到随机分片 (代理 Distributed 表具有隐式的 rand() 分片键) ;若要为查询指定分片,请设置 insert_shard_id。该隐式键仅用于分配插入的行:读取时,该表的行为与没有分片键的 Distributed 表相同 (尤其是,optimize_skip_unused_shards 和 force_optimize_skip_unused_shards 不会将其视为分片裁剪键) 。SHOW CREATE TABLE 会在生成的 Remote(...) 表定义中包含该键,因此基于该定义重新创建的表也能接受多分片 INSERT 查询。
也支持命名集合:
注意事项
- 该引擎是远程服务器的直通视图:不支持对
Remote数据库执行CREATE TABLE、DROP TABLE、ALTER等 DDL 语句。请直接在远程服务器上管理 schema。 - 对已配置的远程用户,访问权限由远程服务器强制执行;本地则按数据库及其表上的常规特权进行控制。
- 用户无权查看的本地分片表会被视为缺失,而非禁止访问。因此,不能通过
Remote数据库探测用户无权访问的本地数据库中的表名。这既适用于列出表 (SHOW TABLES、EXISTS TABLE) ,也适用于解析表 (DESCRIBE TABLE、SHOW CREATE TABLE、SELECT) ;此类表也不会通过其所在分片的远程副本提供。只有在本地副本确实没有该表时,才会触发上述回退机制。 - 列出某个分片的本地副本中存在的数据库的表时,结果还会包含仅存在于该分片远程副本上的表,以确保
SHOW TABLES和system.tables与会回退到这些副本的EXISTS TABLE、DESCRIBE TABLE和SELECT保持一致。当所有远程副本均未响应时,将原样返回本地副本的表列表,因为它已是可用副本的响应结果。 - 如果远程服务器不可用,列出其表 (
SHOW TABLES、system.tables) 时会报告连接错误,而不是返回空表列表,这与对同一数据库执行EXISTS TABLE和SELECT时的行为一致。请注意,当此类数据库无法访问时,查询所有数据库的system.tables的SELECT也会失败。 - 一个
Remote数据库可以指向同一服务器上的另一个Remote数据库。列出和描述此类链中的表无需拥有中间数据库的特权——它既不保存自身的数据,也不保存自身的元数据,并且每一跳都会检查调用方对其所代理对象的权限。相比之下,读取和写入数据需要在链的每一跳都拥有SELECT/INSERT权限,因为查询实际是在中间数据库的表上执行的,这与在另一个Distributed表之上使用Distributed表完全相同。上述可见性规则同样适用于该链:中间数据库对调用方隐藏的表,也不会通过外层数据库的远程副本提供。如果本地副本上的中间数据库无法访问其自身的目标,外层分片的本地副本将完全无法响应——就如同该副本本身已宕机——外层数据库会回退到该分片的远程副本。
示例
system 数据库的 Remote 数据库,并从中读取数据: