一条clickhouse SQL语句引发的问题思考

在这里插入图片描述

前段时间在实际工作中,用户的一条SQL引发了我一些思考。写一篇简单的博文来记录下。实际表的列名等已替换。

SELECT
*
FROM
db1.table1 as t1
LEFT JOIN db2.table2 as t2 ON
t1.col1 = t2.col2
WHERE
t1.time >= '2020-01-01 00:00:00'
AND t1.time < '2020-01-31 00:00:00'
AND t1.col2 in ('5K')

这条SQL语句在clickhouse19.18.1.1版本会报如下异常(这是clickhouse自身的一个bug,在20.3.2.1版本中已修复,2020-03-12)

Code: 48. DB::Exception: Received from localhost:10115. DB::Exception:
Method createColumn() is not implemented for data type Set.

当面对这样一个报错,我们如何着手解决?
先看异常提示:字面意思是某个数据类型集没有实现createColumn。那我们先去掉一些过滤条件看下:

SELECT
*
FROM
db1.table1 as t1
LEFT JOIN db2.table2 as t2 ON
t1.col1 = t2.col2
WHERE
t1.time >= '2020-01-01 00:00:00'
AND t1.time < '2020-01-31 00:00:00'
SELECT
*
FROM
db1.table1 as t1
LEFT JOIN db2.table2 as t2 ON
t1.col1 = t2.col2
WHERE
 t1.col2 in ('5K')

无论上面那种情况都不再报错了。再结合下异常错误提示,我们可以推测,一定是JOIN时,对字段的推导有问题了。那么重点来了,在不升级版本或者干脆这个bug就没修复,客户这边也不想大幅度修改SQL,那我们又该怎么处理?

通过分析,这条SQL就是一条JOIN语句,并且过滤条件全部是一张表的列,那么我们是否可以先利用过滤字段查出一张自表之后,再去JOIN呢?带着这样的思路,我们修改SQL如下:

SELECT
*
FROM (select * from db1.table1 where col2 in ('5K')) as t1
LEFT JOIN db2.table2 as t2 ON
t1.col1 = t2.col2
WHERE
t1.time >= '2020-01-01 00:00:00'
AND t1.time < '2020-01-31 00:00:00'

这次我们发现SQL不再报错了。接着对于clickhouse来说,不要使用select * 这样的影响性能的查询(虽然这样也很快),我们把过滤条件中用到的列查出来即可。SQL改动如下:

SELECT
*
FROM (select col1,col2,time from db1.table1 where col2 in ('5K')) as t1
LEFT JOIN db2.table2 as t2 ON
t1.col1 = t2.col2
WHERE
t1.time >= '2020-01-01 00:00:00'
AND t1.time < '2020-01-31 00:00:00'

到这里我们已经利用子查询,解决了之前的问题。但我们还想再改,我们希望能尽可能跟客户原先的SQL一致,于是我们这次把子查询中的条件再次拿到外层,如下:

SELECT
*
FROM (select col1,col2,time from db1.table1) as t1
LEFT JOIN db2.table2 as t2 ON
t1.col1 = t2.col2
WHERE
t1.time >= '2020-01-01 00:00:00'
AND t1.time < '2020-01-31 00:00:00'
AND t1.col2 in ('5K')

至此,我们在没有更新版本,没有解决bug的情况下,仅仅调整SQL语句就达到了用户想要的目的。具体底层的实现,我们后期可以写一篇博文来了解。
新年第一篇文章,祝各位Happy 牛 year!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值