一些聚合函数的结果跟流入数据的顺序有关,CH文档明确说明这样的函数的结果是不确定的。这是为什么呢?让我们用explain pipeline来一探究竟。

以一个很简单的查询为例:

select any( step ) from events group by request_id;

events表的定义如下:

CREATE TABLE default.events
(
`ID` UInt64,
`request_id` String,
`step_id` Int64,
`step` String
)
ENGINE = MergeTree
ORDER BY ID

该查询从events表里面读取数据步骤 step 和请求ID request_id ,按照request_id分组并取第一个step

我们看一下这个查询的pipeline:

localhost :) explain pipeline select any( `step`) from events group by request_id

┌─explain────────────────────────────────┐
│ (Expression) │
│ ExpressionTransform │
│ (Aggregating) │
│ Resize 32 → 1 │
│ AggregatingTransform × 32 │
│ StrictResize 32 → 32 │
│ (Expression) │
│ ExpressionTransform × 32 │
│ (SettingQuotaAndLimits) │
│ (ReadFromMergeTree) │
│ MergeTreeThread × 32 0 → 1 │
└────────────────────────────────────────┘

可以看出没有sorting步骤。这个查询在多核服务器中速度是相当快的,因为充分利用了多核,直到最后一步才归并成一个数据流由一个线程来处理。

可是要注意 这个查询的结果每次都不一样,可以用加过滤条件的计数来测试,测试的SQL如下:

select countIf(A='step1') from (select any( `step`) as A from (select * from events) group by request_id)

结果是:2500579, 2500635,2500660。结果差距都不大,但都不是绝对正确的结果。这是因为多线程执行时并不能严格保证是按照engine=MergeTree 的表的存储顺序来处理数据的。如果能容忍误差就没问题,因为这个查询的效率是非常高的。

但如果要追求绝对的正确结果。则需要显示地指定顺序,改造查询如下:

select any( step ) from (select * from events order by ID) group by request_id;

查询的pipeline变成这样:

localhost :) explain pipeline select any( step ) from (select * from events order by ID) group by request_id;

┌─explain─────────────────────────────────┐
│ (Expression) │
│ ExpressionTransform │
│ (Aggregating) │
│ AggregatingTransform │
│ (Expression) │
│ ExpressionTransform │
│ (Sorting) │
│ MergingSortedTransform 36 → 1 │
│ (Expression) │
│ ExpressionTransform × 36 │
│ (SettingQuotaAndLimits) │
│ (ReadFromMergeTree) │
│ MergeTreeInOrder × 36 0 → 1 │
└─────────────────────────────────────────┘

注意到pipeline中增加了重要的一步MergingSortedTransform 36 → 1 ,这一步保证了查询的正确性,但是将多个线程的数据流归集到一起,排序后继续由一个线程完成剩下的处理步骤,效率上受到很大的影响。测试结果表示:加了ORDER BY 子句的查询能够得到一致的正确结果,但效率差了至少10倍。越是核数多的服务器,其差距越大。

Clickhouse上用Order By保证绝对正确结果但代价是性能的更多相关文章

  1. 无法在WEB服务器上启动调试,Web 服务器配置不正确

    访问IIS元数据库失败 思考可能是次序出了问题,解决 1.打开CMD,进入 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 2.输入 aspnet_regi ...

  2. git(osx)上的一个git commit无法正确提交的问题

    我发现在我修改我自己的文件之后企图使用git commit编辑更加详细的争对这次提交的信息的时候 我mac上的vi编辑器貌似 出现了问题 大概报这个错. error: There was a prob ...

  3. linux如何判断上一条命令执行是否正确

    echo $? 如果输出0代表结果正确 如果输出非0代表结果错误

  4. php上传文件如何保证上传文件不被改变或者乱码

    很多网站上传文件都截取文件后缀,前面用时间错加后缀组成,然而一下下载的网站并不需要这样,需要保持原来的文件名,这里讲述一下 //上传操作 function uploadify(){ //var_dum ...

  5. 多节点,多线程下发订单,使用zookeeper分布式锁机制保证订单正确接入oms系统

    假设订单下发, 采用单机每分钟从订单OrderEntry接口表中抓100单, 接入订单oms系统中. 由于双十一期间, 订单量激增, 导致订单单机每分钟100单造成, 订单积压. 所以采用多节点多线程 ...

  6. 运行在CentOS7.5上的Django项目时间不正确问题

    在Django的配置文件settings.py中,有两个配置参数是跟时间与时区有关的,分别是TIME_ZONE和USE_TZ 如果USE_TZ设置为True时,Django会使用系统默认设置的时区,即 ...

  7. 在imageView依次加入7个手势, 1.点击哪个button,往imageView上加入哪个手势.(保证视图上仅仅有一个手势). 2.轻拍:点击视图切换美女图片.(imageView上首先展示的美女

    // // ControlView.h // HomeworkGestureRecognizer // // Created by lanouhn on 14-8-27. // Copyright ( ...

  8. jdk8 stream实现sql单表select a,b,sum(),avg(),max() from group by a,b order by a,b limit M offset N及其性能

    之所以要测该场景,是因为merge多数据源结果的时候,有时候只是单个子查询结果了,而此时采用sql数据库处理并不一定能够合理(网络延迟太大). 测试数据10万行,结果1000行 limit 20 of ...

  9. 如何在HTML5 Canvas 里面显示 Font Awesome 图标

        Font Awesome 是一套完美的图标字体,主要目的是和 Bootstrap 搭配使用. 提供的CSS 已经可以完美显示这些图标在网页里面.最新的版本4.3 里面,已经提供519 Icon ...

随机推荐

  1. C# 给Word每一页设置不同图片水印

    Word中设置水印时,可加载图片设置为水印效果,但通常添加水印效果时,会对所有页面都设置成统一效果,如果需要对每一页或者某个页面设置不同的水印效果,则可以参考本文中的方法.下面,将以C#代码为例,对W ...

  2. 用 JuiceFS 备份 Nginx 日志可以这么简单

    在我们线上的生产环境中要备份的东西很多,各种服务日志.数据库数据.用户上传数据.代码等等.用 JuiceFS 来备份可以节省你大量时间,我们会围绕这个主题写一系列的教程,整理出一套最佳实践,方便大家. ...

  3. (二) operator、explicit与implicit 操作符重载

      有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成把两个整 ...

  4. Oracle分析函数/排名函数/位移函数/同比环比

    分析函数 作用:分析函数可以在数据中进行分组,然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计值.统计函数:MAX(字段名).MIN(字段名).AVG(字段名).SUM(字段名).CO ...

  5. git问题:gpg failed to sign the data fatal: failed to write commit object问题

    今天用版本控制工具git提交时一直出现的问题:gpg  failed to sign the data fatal: failed to write commit object, gpg是一个加密软件 ...

  6. 2020ICPC南京 M.Monster Hunter

    题目大意 一颗根为 \(1\) 的有 \((2≤≤2000)\) 个节点的树,每个节点有一个权值 \(ℎ_{} (1≤ℎ_{}≤10^9)\) ,能删除某个点的前提是其父亲节点已经被删除,并且删除一个 ...

  7. JZ-015-反转链表

    反转链表 题目描述 输入一个链表,反转链表后,输出新链表的表头. 题目链接: 反转链表 代码 /** * 标题:反转链表 * 题目描述 * 输入一个链表,反转链表后,输出新链表的表头. * 题目链接: ...

  8. C#读写自定义的多字段配置文件

    mark一下,日后填坑 参考: WPF 读写自己写的配置文件

  9. CSAPP-Lab01 Data Lab 记录

    总览 Problem-int bitXor bitXor - x^y using only ~ and & Example: bitXor(4, 5) = 1 Legal ops: ~ &am ...

  10. 分享自研实现的多数据源(支持同DB不同表、跨DB表、内存数据、外部系统数据等)分页查询工具类实现原理及使用

    思考: 提起分页查询,想必任何一个开发人员(不论是新手还是老手)都能快速编码实现,实现原理再简单不过,无非就是写一条SELECT查询的SQL语句,ORDER BY分页排序的字段, 再结合limit ( ...