Clickhouse表连接

本文探讨了在ClickHouse中,如何避免JOIN操作的内存溢出和效率问题,通过对比方案一的JOIN、方案二的Join表引擎和方案三的Dictionary字典。作者推荐使用Dictionary字典,因为它能有效提升查询效率,尤其适用于小表关联场景。然而,当数据量过大时,需考虑字典的内存限制和数据同步问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

        datas表是原始数据表(见下图),现在要对datas表中的app类型进行分析。于是需要建立一张app名称与app类型关系表,对两张表进行连接查询。

方案一

简单粗暴,直接建立关联表,直接进行join关联。

--建立关联表
create table app_type_mapping(
`m_app` String,
`m_type` String
)ENGINE = TinyLog

--插入数据
insert into app_type_mapping values('app-1','system app'),('app-2','core app')('app-3','3th-party app')

--查询
select d_id,d_app,if(m_type='','other',m_type) as app_type
from datas  left join app_type_mapping  on d_app=m_app

结果:

看起来并没什么问题。但是clickhouse对于普通join内部的实现原理利用右表构建一个hash table并加载到内存中,于是会存在2个问题:

        1. 内存溢出问题:右边数据量超过机器可用内存空间的限制,则JOIN操作无法完成

        2. 效率问题:每次join都需要从磁盘中读取整个右表数据加载到内存   

         针对问题一,一般将数据量小的表作为右边。如果两张表数据量都特别大怎么办,没办法,那就只能从源头解决,建立大宽表把所有需要的字段都放进去。

方案二

使用Join表引擎。本文仅作简单的介绍,正式环境使用Join表还需要考虑数据同步问题,详细操作可参考这篇文章:https://guides.tinybird.co/guide/faster-joins-with-the-join-engineicon-default.png?t=LBL2https://guides.tinybird.co/guide/faster-joins-with-the-join-engine

--删除前面建立的关联表
drop table app_type_mapping;

--新建关联表,采用Join表引擎
create table app_type_mapping(
`m_app` String,
`m_type` String
)ENGINE = Join(ALL, LEFT, m_app)

--重新插入数据
insert into app_type_mapping values('app-1','system app'),('app-2','core app')('app-3','3th-party app')

--查询
SELECT d_id,d_app,if(m_type='','other',m_type) as app_type
FROM datas
ANY LEFT JOIN app_type_mapping USING (d_app)

 结果:

        使用Join表引擎的表数据会一直保存在内存中,当新的数据插入的时候,Clickhouse会写入磁盘以便故障时数据恢复。由于数据直接就可以从内存中获取,不需要先从磁盘加载到内存,减少了IO,从而提交了查询效率。

 方案三(推荐)

使用dictionary 字典。在方案一的基础上建立dictionary。

--新建dictionary
CREATE DICTIONARY app_type_dict(
  `m_app` String,
  `m_type` String
)
PRIMARY KEY m_app
SOURCE(CLICKHOUSE(HOST '172.**.**.***' PORT 9000 USER 'default' TABLE 'app_type_mapping' PASSWORD '***'))
LAYOUT(COMPLEX_KEY_HASHED())
LIFETIME(30)

--查询
select d_id,d_app,dictGetStringOrDefault('app_type_dict','m_type',tuple(d_app),'other') as app_type
from datas 

结果:

         dictionary天生就很适合用于这种关联表或者中间表的场景,它跟Join表引擎一样将数据存在内存中,并且比join更加简单和高效。dictionary的强大之处在于它不仅支持将内部表加载到字典中(内部字典),还支持外部字典,可以将其他数据源(如Mysql,Redis等)的数据通过HTTP加载到字典中。无论是内部字典还是外部字典,数据表中的数据一旦发生更新,字典中的数据随后也会更新。

总结

1. Clickhouse进行表连接时,表数据量小且不追求效率直接用join语句,需要遵循“小表在右”原则

2. Join表引擎和dcitionary都会将数据保存到内存中,以提高查询效率,更推荐使用dcitionary

3. dcitionary也不是万金油,由于内存限制,当连接表超过1百万条数据,就不要使用字典了,需要从其他方向考虑优化

### ClickHouse 远程连接配置方法 为了实现 ClickHouse 的远程连接,需要对服务器的配置文件进行修改,并确保防火墙规则允许外部访问。以下是详细的配置方法和注意事项: #### 1. 修改配置文件 ClickHouse 默认只监听本地连接(`localhost`),因此需要修改配置文件以支持远程连接。配置文件位于 `/etc/clickhouse-server/config.xml`。 - 打开配置文件并取消以下行的注释: ```xml <listen_host>::</listen_host> ``` 此操作使得 ClickHouse 监听所有网络接口,从而允许远程连接[^1]。 - 如果需要更改默认端口(9000 用于客户端连接,8123 用于 HTTP 接口),可以使用 `sed` 命令批量替换端口号: ```bash sed -i "s/9000/5566/g" /etc/clickhouse-server/config.xml ``` 替换后需要重启 ClickHouse 服务以使更改生效[^2]。 #### 2. 配置用户权限 ClickHouse 默认用户为 `default`,密码存储在 `/etc/clickhouse-server/users.d/default-password.xml` 中。如果需要启用远程访问,可以删除该文件以移除密码限制(不推荐生产环境使用)[^2]。 此外,可以通过新增用户并分配权限的方式增强安全性。例如: ```sql CREATE USER remote_user IDENTIFIED WITH plaintext_password BY 'password'; GRANT ALL ON *.* TO remote_user; ``` 上述命令创建了一个名为 `remote_user` 的用户,并赋予其所有权限[^4]。 #### 3. 确保防火墙规则开放 为了允许远程机器访问 ClickHouse,必须确保防火墙开放了相关端口(默认为 9000 和 8123)。可以使用以下命令检查并开放端口: ```bash sudo firewall-cmd --zone=public --add-port=9000/tcp --permanent sudo firewall-cmd --zone=public --add-port=8123/tcp --permanent sudo firewall-cmd --reload ``` #### 4. 测试远程连接 完成上述配置后,可以使用客户端工具(如 DataGrip 或命令行工具)测试连接。例如: ```python import clickhouse_driver client = clickhouse_driver.Client(host='your_server_ip', port=5566, user='remote_user', password='password') result = client.execute('SELECT 1') print(result) ``` --- ### 注意事项 - 在生产环境中,建议避免直接暴露 ClickHouse 到公网,可通过反向代理或 SSH 隧道增强安全性。 - 如果启用了密码验证,请确保客户端连接时提供正确的用户名和密码[^4]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值