在线精品99_中国九九盗摄偷拍偷看_91免费版在线观看_91.app_91高清视频在线_99热最新网站

ClickHouse是如何批量写入的

171次阅读
没有评论

共计 2333 个字符,预计需要花费 6 分钟才能阅读完成。

这篇文章将为大家详细讲解有关 ClickHouse 是如何批量写入的,文章内容质量较高,因此丸趣 TV 小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

简介

批量写入又称为 bulk write,对于单表插入多条数据的场景,可以减少插入请求数量,提高吞吐量和效率。clickhouse 官方 Golang 驱动 clickhouse-go[1]支持该关键特性,但是文档的介绍不是很详细,只有一句:

Bulk write support : begin- prepare- (in loop exec)- commit

 

并没有详细介绍用法和原理,笔者在开发业务时使用的库是 sqlx[2],sql 也支持 clickhouse-go 驱动。参考了官方样例代码[3]:

...
tx, err := connect.Begin()
checkErr(err)
stmt, err := tx.Prepare(INSERT INTO example (country_code, os_id, browser_id, categories, action_day, action_time) VALUES (?, ?, ?, ?, ?, ?) )
checkErr(err)

for i := 0; i   100; i++ {
 if _, err := stmt.Exec(
  RU ,
 10+i,
 100+i,
 []int16{1, 2, 3},
 time.Now(),
 time.Now(),
 ); err != nil {
 log.Fatal(err)
 }
}
...

 

我写的 bulk write 类似上面的代码,但是提交给同事 review 时,他提出了疑问:stmt.Exec 是每次执行都发送写请求到数据库吗?这个问题其实我不敢肯定,官方文档也说得不明确。考虑到严谨性,让自己的 PR 更有说服力,自己去翻看了相关源代码。

这里需要指出,如果利用编辑器里的代码跳转功能会跳到 database/sql 库中的 Exec 函数实现,实际上我们要看的代码是 clickhouse-go 中的实现,至于编辑器跳转到 database/sql 中的原因,书写此文时笔者也没弄清楚,先挖个坑吧。

  核心实现

stmt.Exec 的核心代码如下[4]:

func (stmt *stmt) execContext(ctx context.Context, args []driver.Value) (driver.Result, error) {
 if stmt.isInsert {
 stmt.counter++
 if err := stmt.ch.block.AppendRow(args); err != nil {
 return nil, err
 }
 if (stmt.counter % stmt.ch.blockSize) == 0 {
 stmt.ch.logf([exec] flush block )
 if err := stmt.ch.writeBlock(stmt.ch.block); err != nil {
 return nil, err
 }
 if err := stmt.ch.encoder.Flush(); err != nil {
 return nil, err
 }
 }
 return emptyResult, nil
 }
 if err := stmt.ch.sendQuery(stmt.bind(convertOldArgs(args))); err != nil {
 return nil, err
 }
 if err := stmt.ch.process(); err != nil {
 return nil, err
 }
 return emptyResult, nil
}

 

上面的代码不多,非常清晰,当执行 Exec 时,stmt.ch.block.AppendRow(args)会先把 sql 参数附加到本地缓存 block 中,然后 (stmt.counter % stmt.ch.blockSize) 判断本地缓存大小是否到达阈值,到达则执行 Flush(),将数据写入远端。综上,clickhouse-go 中的核心实现逻辑是:

底层维护一个缓存 block,同时设置 block_size 控制缓存大小执行 stmt.Exec 时,不会直接写入远程 ClickHouse 中,而是将插入参数 Append 到 block 中每次 Append 后,判断 block 的 size 和 block_size 的关系,如果正好整除,则刷新 block(即写入 clickhouse)

因此 block_size 这个参数很重要,它表示本地缓存的上限,如果很大的话,程序会占用一些内存。笔者起初设置为 100000,在调试日志中看不到 stmt.ch.logf([exec] flush block )打印的 log,设置小后就看到下面的输出:

...
[clickhouse][connect=1][begin] tx=false, data=false
[clickhouse][connect=1][prepare]
[clickhouse][connect=1][read meta]  - data: packet=1, columns=6, rows=0
[clickhouse][connect=1][exec] flush block
[clickhouse][connect=1][exec] flush block
....

 
 

关于 ClickHouse 是如何批量写入的就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计2333字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)
主站蜘蛛池模板: 亚洲av永久无码精品表情包 | 色综合另类小说图片区 | 国产精品成人va在线观看 | 久草观看| 婷婷久久久亚洲欧洲日产国码av | 成人免费看的a级毛片 | 久久久久se色偷偷亚洲精品av | 内射中出日韩无国产剧情 | 免费观看黄频视 | 国产自产精品 | 亚洲一级毛片视频 | 欧美变态口味重另类在线视频 | 亚洲中文字幕久久精品无码喷水 | 偷拍小视频99在线 | 精人妻无码一区二区三区 | 柠檬福利精品视频导航 | 男女男精品视频免费观看 | 国产精品免费看久久久香蕉 | 国产精品人人爱一区二区白浆 | 国产一区二区三区免费播放 | 国产一级爱做片免费观看 | 亚洲第一页在线 | 国内精品伊人久久久久av影院 | 台湾无码一区二区 | 欧美深深色噜噜狠狠yyy | 97亚洲色欲色欲综合网 | 我国产码在线观看av哈哈哈网站 | 欧美日本高清一本二本三本 | 国产一区二区三区在线观看免费 | 影音先锋中文无码一区 | 最新理伦片eeuss影院 | 作爱视频在线免费观看 | 99久久精品免费看国产麻豆 | 无码国产一区二区三区四区 | 国产午夜视频在线观看网站 | 中文无码伦av中文字幕 | 亚洲精品一区二区三区在 | 日韩a在线观看免费观看 | 被黑人猛躁10次高潮视频 | 国产sm鞭打折磨调教视频 | 亚洲国产另类久久久精品黑人 |