Clickhouse: One table to rule them all!

前面几篇笔记我们讨论了存储海量行情数据的个人技术方案。它们之所以被称之为个人方案,并不是因为性能弱,而是指在这些方案中,数据都存储在本地,也只适合单机查询。

数据源很贵 – 在这个冬天,我们已经听说,某些上了规模的机构,也在让员工共享万得账号了。所以,共享网络存储,从而只需要一个数据账号,就成为合理的需求。更不必说,集中管理才可能让 IT 来进行数据维护,而分析师只需要专注于策略就好。

那些以讹传讹的解决方案

都已经 2024 年了,但说到行情数据的存储,你仍然能看到推荐 mysql 的文章。这完全是错误的。不要说 mysql,就是 postgres 来了也不行。不要说 postgres,就是 sqlserver 甚至 oracle 来了都不行。

其它不 work 的方案还包括 mongodb。mongodb 是挺能装的,但是它不适合行情数据这类时序数据的查询。

Influxdb 是最早和最出名的时序数据库。但是它的社区版本性能还是偏弱,特别是它限制了查询的并发度。此外,它的引擎是 Go 语言,这仍然要比 C 慢好几倍。

Dolphinedb 可能性能上强于 Influxdb 不少,但缺点也是社区版对性能的限制太多。Tidb 据说性能不错,但我们没有机会评测过它。

不过如果有犹如王者般的 clickhouse 社区版摆在面前,还有什么必要去评估那些青铜呢?

Why click house is so f**ing fast?

Clickhouse 是战斗民族开发的产品。它的开发者是俄国的搜索引擎 Yandex!(提到 Yandex! 时,不能漏了这个感叹号)。搜索引擎天生要处理很多查询和统计分析,所以就催生了这个性能怪兽。


Clickhouse 的优化是全方位的。在硬件级别上,它利用了 SIMD CPU 指令。Clickhouse 特别强调他们使用了 SIMD 指令来进行并行优化,当你安装 clickhouse 时,它提供了一个检测工具,让你检测 SIMD 指令优化能否开启。

在这里插入图片描述

数据结构上,Clickhouse 使用了列存储,这一点,其实像 parquet, hdf5 都是这样存储的。基于列存储,就有很多很好的压缩方案可用,一旦存盘的数据量变小,显然易见 IO 效率也会提升。

但是它基于 merge-tree 的存储引擎,使得在查询上,不仅可以利用所有的 CPU 核和磁盘、还可以利用集群的所有 CPU 核和磁盘。这使得它的查询性能可以随硬件增加线性扩展。

在这里插入图片描述

在这一块,确实用了很多大数据的技巧,比如使用了 bloomfilter 的索引。它还留了一些优化技巧给使用者,这也是我们这篇笔记将要介绍的:如何设计一个能存储上百亿条行情数据的数据库,并达到最佳性能。

实战!先存一个小目标

尽管在 clickhouse 中,我们可以把分钟线与日线存在一张表里,但是考虑到我们几乎不可能同时取两个不同周期的数据,所以,把它们分别按表存储显然更合理。所以,我们在举例时,就只以分钟线为例:

CREATE TABLE if not exists bars_1m
(`frame` DateTime64 CODEC(Delta, ZSTD),`symbol` LowCardinality(String),`open` Float32 DEFAULT -1 CODEC(Delta, ZSTD),`high` Float32 DEFAULT -1 CODEC(Delta, ZSTD),`low` Float32 DEFAULT -1 CODEC(Delta, ZSTD),`close` Float32 DEFAULT -1 CODEC(Delta, ZSTD),`volume` Float64 DEFAULT -1 ,`money` Float64 DEFAULT -1 ,`factor` Float64 DEFAULT -1 CODEC(Delta, ZSTD)
)
ENGINE = MergeTree
ORDER BY (frame, symbol)

这里我们看到使用 clickhouse 的第一个好处。它完全兼容了 sql 的核心语法。要知道在设计 zillionare 2.0 版时我们被 influxdb 折磨的不行 – 天知道他们为什么抛弃了原先对 sql 的兼容,而独出心裁地设计了一种全新的查询语言!

这意味着如果我们在团队内安装了 clickhouse – 这常常是 IT 的活,分析师也就能直接上手 – 因为做数据分析的人,你们都是懂 sql 的。

这里有一些技巧,是普通的 SQL 中没有的。

首先是 frame 字段中的 CODEC(Delta, ZSTD) 压缩。它巧妙地通过行间数据的差值,将列数据转换成为一个稀疏的数据向量 – 这样可以大大减少存储空间和读取时间。实际上,在行情数据中,大量的时间戳都是相同的,或者只有很小的 delta。比如,如果我们把 5000 多支个股的分钟数据存入一张表,那么我们常常会看到连续 5000 个相同的时间戳,这些都可以存为 0!

OHLC 中的 default 值也给得颇有讲究。如果某天某个标的停牌,那么它的 OHLC 等数据就是空值。clickhouse 允许我们存空值。但这样一来,clickhouse 必须使用另外的文件来存储空值,并在查询时再通过 join 把空值连接起来。这会花掉一些时间。所以,这里我们使用了一个不可能的值作为默认值,这样所有的数据仍然存在一起,将会加快存储和运算速度。

OHLC 数据的变化都很小,所以我们也通过 DELTA 编码压缩它们。而成交量和成交额的跳动则可能很大,启用压缩就会得不偿失。

我们能做这些优化,是因为我们知道数据的分布特性 – 就像数据分析师也必须懂得数据的分布特性一样 – clickhouse 也是这样才能做好优化。

我们在 OHLC 数据上使用了单精度,但对 factor 却使用了 64 位浮点数。这是必要的,尽管看上去它们都很小,但是,OHLC 数据的取值范围很小,不会有精度问题,而 factor 数据则不一样,它必须更准确。
在这里插入图片描述

Symbol 字段我们也使用了一种优化。通过这种编码,我们实际上在存储 Symbol 时,存储的是整数而非字符串,这样会大大提高存储效率和查询速度。这个方法,如果你熟悉 Pandas 的性能优化,就应该已经见过了 – 它就是类似于 pandas 的 categorize 优化。

最后,我们把 frame 和 symbo 设为主键。我们的大多数查询将基于这样两个字段的比较。


我们设计的表,性能究竟怎么样?

让我们先分别存入 100 万条、1000 万条和 1 亿条数据,并且分别计算插入时间和查询时间。在准备数据时,我们使用了全随机的数据,这点很重要。如果我们都使用相同的数据,那么速度会快一些。

  • 写入 1 百万条数据,用时 8.3 秒,查询结果为 200 行时,用时 0.1 秒。
  • 写入 1 千万条数据,用时 77.7 秒,查询结果为 2000 行时,用时 0.7 秒。
  • 写入 1 亿条数据,用时 16 分钟左右,查询结果为 20200 行时,用时 13.7 秒。

这个结果已经很优秀了。但还看上去并没有超出预期,对吧?作为对比,我们在 influxdb 上,返回 100 万条记录时,花费 55 秒左右,其中网络传输和客户端重新组装数据占约 30 秒),这样看来,clickhouse在这一局很可能还没有超过influxdb。另外,在 1000 万级别下,优化到极致的 mysql 也能做到0.7秒以内的查询,不过它处理不了上亿条数据。

为什么没有惊喜?我去看了一下我的测试环境:

一个只有 8CPU,8GB 的虚拟机(当然底层是磁盘阵列),并且我已经开了 4 个 vscode 窗口,这样系统只剩下0.6GB的自由内存。我们测试Influxdb时,使用的是物理机,48CPU+96GB内存,总记录是30多亿条。

改天再找机会在同样的环境下进行对比测试。不过,clickhouse 员工已经在类似的行情数据库上进行了测试:

在一台 macbook pro 上,在 2.4 亿条记录中,进行 argmax 的查询,只用了 0.9 秒!这个速度虽然不够跑高频,但已足够多数场景下使用了。

不过,clickhouse 的测试与我们的测试有很大差别:

在 clickhouse 的测试中,它返回的数据量很小;而在我们的测试中,要求查询返回了 2 万条数据。

这是另一个优化方向。把能做的事情放到 clickhouse server 端做。也就是,很多因子的计算,之前我们需要取数据回 python 端再计算的,现在如果有可能,直接让 clickhouse 来做,我们只要结果。

这是我们后续笔记要发表的内容。

量化数据本地化方案全系列发布在大富翁量化网站的这个合集下,欢迎前往一次性读完!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/629395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python进程池multiprocessing.Pool

环境: 鲲鹏920:192核心 内存:756G python:3.9 python单进程的耗时 在做单纯的cpu计算的场景,使用单进程核多进程的耗时做如下测试: 单进程情况下cpu的占用了如下,占用一半的核心数: 每一步…

数据结构实战:变位词侦测

文章目录 一、实战概述二、实战步骤(一)逐个比较法1、编写源程序2、代码解释说明(1)函数逻辑解释(2)主程序部分 3、运行程序,查看结果4、计算时间复杂度 (二)排序比较法1…

ADA-YOLO:YOLOv8+注意力+Adaptive Head,mAP提升3%

生物医学图像分析中的目标检测和定位至关重要,尤其是在血液学领域,检测和识别血细胞对于诊断和治疗决策至关重要。虽然基于注意力的方法在各个领域中目标检测方面取得了显著的进展,但由于医学影像数据集的独特挑战,其在医学目标检…

JUC的常见类

目录 Callable ReentrantLock Semaphore CountDownLatch JUC即 java.util.concurrent,其中存放了一些进行多线程编程时有用的类 Callable Callable是一个接口,在我们实现Runnable创建线程时,Runnable关注的是其过程,而不关注…

MySQL实现跨库join查询

MySQL实现跨库join查询 一.同服务器的不同库 只需要在表名前加上db_name select* fromuserdb.user u join orderdb.order o onu.id o.user_id;二.不同服务器的不同库 查看配置 FEDERATED SHOW engines;如果是NO,需要改为YES.默认是NO 在my.ini文件中增加一行,…

Kotlin 进阶

1.lambda 表达式 package com.jmj.myapp.lamdbaimport javax.security.auth.callback.Callbackfun main() {1.test1 {println(this1) }}fun <T> T.test1(callback:T.() -> Unit) {this.callback() }package com.jmj.myapp.lamdbaimport javax.security.auth.callback…

HCIA——11计算机网络分层结构——OSI/ISO、TCP/IP

学习目标&#xff1a; 参考模型 计算机网络 1.掌握计算机网络的基本概念、基本原理和基本方法。 2.掌握计算机网络的体系结构和典型网络协议&#xff0c;了解典型网络设备的组成和特点&#xff0c;理解典型网络设备的工作原理。 3.能够运用计算机网络的基本概念、基本原理和基本…

​​社交媒体与新闻:Facebook在信息传播中的作用

社交媒体已经成为我们获取和传播新闻的主要渠道之一&#xff0c;而Facebook作为社交媒体的巨头&#xff0c;在信息传播中扮演着举足轻重的角色。本文将深入探讨社交媒体对新闻传播的影响&#xff0c;聚焦于Facebook在这一领域的独特作用&#xff0c;以及这种作用对我们的新闻体…

2024华数杯国际赛A题16页完整思路+五小问py代码数据集+后续高质量参考论文

这回带大家体验一下2024“华数杯”国际大学生数学建模竞赛呀&#xff01; 完整内容获取在文末 此题涉及到放射性废水从日本排放到海洋中的扩散问题&#xff0c;以及对环境和人类健康的潜在影响。 ## 问题重述 1. **预测污染范围和程度&#xff1a;** - 使用数学模型描述放射性…

springboot-简单测试 前端上传Excel表格后端解析数据

导入依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxm…

【保姆级教程|YOLOv8添加注意力机制】【2】在C2f结构中添加ShuffleAttention注意力机制并训练

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

Ubantu 安装vscode配置c/c++环境

文章目录 安装VSCode注意 snap包冲突 安装C/C编译环境注意 进程锁占用 配置C开发环境安装插件配置tasks.json配置c_cpp_properties.json 配置调试环境配置 launch.json 安装VSCode 方式一&#xff1a;ubantu 软件里面直接安装 方式二&#xff1a;官网下载deb安装包https://cod…

新增PostgreSQL数据库管理功能,1Panel开源面板v1.9.3发布

2024年1月15日&#xff0c;现代化、开源的Linux服务器运维管理面板1Panel正式发布v1.9.3版本。 在这一版本中&#xff0c;1Panel新增了PostgreSQL数据库管理功能&#xff0c;并且支持设置PHP运行环境扩展模版。此外&#xff0c;我们进行了30多项功能更新和问题修复。1Panel应用…

Android性能优化 | DEX 布局优化和启动配置文件

Android性能优化 | DEX 布局优化和启动配置文件 引言 使用DEX布局优化和启动配置文件是优化Android应用性能的有效途径。DEX布局优化可以通过优化应用程序中的DEX文件布局&#xff0c;从而加快Android应用的启动速度和执行速度。启动配置文件则提供了一种灵活的方式来控制应用…

股票涨跌原理

相信很多人都知道&#xff0c;在每一个价位上成交的多头订单和空头订单的数量都是相等的&#xff0c;那为什么会上涨和下跌&#xff0c;背后的原理是什么&#xff1f; 举个生活中的例子&#xff1a; 其实在交易市场上的成交与我们日常生活中的买卖商品成交是类似的&#xff0…

【杂谈】如何测试EEPROM可以保存数据100年以及擦写次数,磨损均衡问题,阿伦尼乌斯方程的老化测试法

【引出问题】 引用帖子&#xff1a;How Do You Test If An EEPROM Can Hold Data For 100 Years? | Hackaday 在hackaday上看到一篇有意思的帖子&#xff0c;如何测试 EEPROM 是否可以保存数据 100 年以及EERPOM的耐久性问题 比如Microchip的文档里面介绍&#xff0c;EEPRO…

C++I/O流——(4)格式化输入/输出(第一节)

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 含泪播种的人一定能含笑收获&#xff…

独立服务器和云服务器的区别

独立服务器和云服务器的区别是很多用户在选择服务器时要做的课程&#xff0c;那么独立服务器和云服务器的区别有哪些呢? 独立服务器和云服务器是两种不同的服务器部署方式&#xff0c;它们在性能、成本、资源利用、安全性和维护等方面存在显著差异。 1. **性能对比**&#xff…

【DC-6靶场渗透】

文章目录 前言 一、确定靶场地址 二、信息收集 三、账号枚举并破解 四、寻找漏洞 五、反弹shell 六、提权 前言 今天做一下DC6靶场 一、确定靶场地址 1、查看靶机mac地址 2、kali使用nmap&#xff0c;arp-scan工具扫描 nmap -sn 172.16.100.0/24 arp-scan 172.16.100.0/24 I…

Kali Linux保姆级教程|零基础从入门到精通,看完这一篇就够了!(附工具包)

作为一名从事网络安全的技术人员&#xff0c;不懂Kali Linux的话&#xff0c;连脚本小子都算不上。 Kali Linux预装了数百种享誉盛名的渗透工具&#xff0c;使你可以更轻松地测试、破解以及进行与数字取证相关的任何其他工作。 今天给大家分享一套Kali Linux资料合集&#xf…