














这是一个创建于 913 天前的主题,其中的信息可能已经有所发展或是发生改变。
我有一个 3000w 行的数据表,我需要在这个表上统计从某一年开始新参保的人数,原数据库是 ORACLE ,用的是
AND A.AAC001 NOT EXISTS
(SELECT 1
FROM AC02_TEMP AS B WHERE A.AAC001 = B.AAC001 AND
B.AAC030 < '2018-01-01 00:00:00')
的语法,在 clickhouse 上我试了 LEFT JOIN 和 NOT IN ,性能均不理想
SELECT COUNT(1) AS "新参保人数"
FROM AC02_TEMP AS A
WHERE A.AAB301 IN (SELECT AAB301 FROM AA26 WHERE AAA148 = '130800')
AND A.AAE200 = '41'
AND A.AAC031 = '1'
AND A.AAC030 >= '2018-01-01 00:00:00'
AND A.AAC001 NOT IN
(SELECT B.AAC001
FROM AC02_TEMP AS B
WHERE B.AAC030 < '2018-01-01 00:00:00');
以下是 explain
CreatingSets (Create sets before main query execution)
Expression ((Projection + Before ORDER BY))
Aggregating
Expression (Before GROUP BY)
ReadFromMergeTree (default.AC02_TEMP)
Indexes:
PrimaryKey
Keys:
AAC001
AAE200
" Condition: and((AAC001 notIn 18692488-element set), (AAE200 in ['41', '41']))"
Parts: 2/2
Granules: 4821/4821
CreatingSet (Create set for subquery)
Expression ((Projection + Before ORDER BY))
ReadFromMergeTree (default.AA26)
Indexes:
PrimaryKey
Condition: true
Parts: 1/1
Granules: 1/1
我是 clickhouse 新手,目前没什么头绪,求大佬帮助 0.0
2 pushMeUp 2023 年 12 月 13 日这样子可以不? |
3 OOKAMI 2023 年 12 月 13 日用 UNION ALL 来做减法汇总试试? SELECT SUM(CNT) UNION ALL |
4 sunrealzhang 2023 年 12 月 13 日@sss15 感谢您的回复,首先连接处应该是 ON t0.TID = A.AAC001 ,然后,AAC001 是这张表的联合主键之一,类型为 Int64 ,未关联上时值不是 NULL 而是 0 (这一点我也不知道为什么要这么实现,按理说未关联上不应该是 NULL 吗),然后我执行了 该查询,依然很慢 执行计划 ``` |
5 sunrealzhang 2023 年 12 月 13 日@OOKAMI 感谢您的回复,实际上,clickhouse 对 EXISTS 语法不完全支持,特别是子查询中无法引用外部表和列,这会导致执行时提示 Missing columns: 'A.AAC001',这也是我将 oracle 中的 NOT EXISTS 改成 NOT IN 的原因 |
6 sunrealzhang 2023 年 12 月 13 日这个 sql 给我整不会了,开始感觉如果不对表结构和数据进行处理,无法通过这个数据库来满足我们的统计分析需求 0.0 |
7 9yu 2023 年 12 月 13 日 via iPhone不是很懂 SQL 但是楼主的回复都很有礼貌和条理。我绝对想和楼主这样认真的人做同事。 |
8 OOKAMI 2023 年 12 月 13 日不懂 clickhouse ,硬要一个 SQL 出来结果的话,这个行不行,按日期分两段去重查 KEY ,再统计,最后去除重复的,这样也没有大数据集匹配 SELECT COUNT(1) |
9 hicdn 2023 年 12 月 13 日 via Android看场景,你是要一次性导出数据还是在业务系统里需要动态查询? 如果是一次性导出数据,直接 dump 整表,然后在 python 里用 set 加载,判断 in |
10 Terry166 2023 年 12 月 13 日In Oracle we can only put up to 1000 values into an IN clause. 解决方案: |
11 512357301 2023 年 12 月 13 日 via Androidck 的 join 是大短板,更何况是子查询。。。 |
12 Maboroshii 2023 年 12 月 13 日离线查出所有人的首次参保时间, 然后新增数据的时候,也新增到这个首次参保时间表? 然后直接查这个首次参保时间就可以了。 |
13 sunrealzhang 2023 年 12 月 14 日@hicdn 动态查询,我们准备把 oracle 的部分可能会导致高负载的查询统计 sql 转移到统计分析类数据库 clickhouse 上 |
15 sunrealzhang 2023 年 12 月 14 日@9yu 感谢您的回复,实际上在 Oracle 上我们使用的 NOT EXISTS ,我想在 clickhouse 上,我们需要在数据同步时对数据本身进行额外的预处理来缓存首次参保状态,原封不动的使用 clickhouse 来支持完成业务需求是我们的一厢情愿 0.0 |
18 sunrealzhang 2023 年 12 月 14 日@OOKAMI 感谢您的回复,我仔细看了下,语义应该和我的需求不符,如果某个 AAC001 未命中第一段 join 而只命中了第二段 join ,依然能被查出来,而它并不是 2018 年开始新参保,而是 2018 年之前有过参保记录。 |
20 512357301 2023 年 12 月 15 日 via Android@sunrealzhang 类型为 Int64 ,未关联上时值不是 NULL 而是 0 (这一点我也不知道为什么要这么实现,按理说未关联上不应该是 NULL 吗) 这是 ck 的特性,未关联上的,会根据字段类型返回默认值,int 是 0 ,string 是'',其他的没研究 |
21 dyv9 2024 年 3 月 20 日 via Android做报表分析就不该实时查询,先建表,将首次参保读取保存,可分段构建这个表,比如跑循环一年一年地构建。 数据仓库 dtl 软件像 pentaho kettle 可支持这种场景,还可调度任务定时处理。做报表就要放弃直接在实时查询,一定要分步骤加工数据到基本维度表,然后叠加。 |
22 kemistep 5 月 15 日使用 bitmap 查询,并且建表的时候,可以使用 hash user_id |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。