Skip to content

Chunk分块数据读取

Tuuz edited this page Feb 18, 2024 · 7 revisions

Chunk分块数据读取(原版)

  • Chunk : 分块处理数据,当要处理很多数据的时候, 我不需要知道具体是多少数据, 我只需要每次取limit条数据,
  • 然后不断的增加offset去取更多数据, 从而达到分块处理更多数据的目的
	db := tuuz.Db().Table("bot_default_reply")
	db.Chunk(1, func(data []gorose.Data) error {
		fmt.Println(Jsong.Encode(data))
		return nil
	})

ChunkWG分块数据读取(仅Gorose-Pro支持)

  • ChunkWG是保留Chunk的使用方法的基础上,新增多线程读取&多线程执行的方式,注意onetime_exec_thread不宜过多,推荐4,不宜过大因为采用的是盲读的方法

读取原理

  • 第一条采用和chunk一样的单线程读取,确保sql等执行是成功的
  • 如果第一条成功的请款下,从第二条开始将会开启多线程盲读
  • 理论上来说线程数与性能是二次曲线,如果你的数据量足够多,性能越好,但是当数据量少,线程多的情况可能反而导致严重的performance impact,所以需要使用什么模式你需要根据数据量来决定,不过设定为4是一个比较合适的值
  • 无论是WG还是非WG功能,都是通过重复的去读取数据库存取数据来实现功能的,所以这个功能和你手动去调用来说其实没啥太大的区别

性能说明&什么时候建议使用

  • 在研究后,有些情况下会提高性能
    • 你的SQL十分的简单,但是数据量很大,你不想在业务代码里面手动写很多的for
    • 你的SQL取回的单条数据量很大,你需要GorosePro直接提供性能更高的方法,不然多线程入侵业务代码
  • 性能劣化的情况
    • 你的原始SQL动作很复杂,复杂的SQL查询,又不能做到index hit,那么这个时候每次执行SQL的时间就很长,这种请款下如果使用每次读取一条chunk的方法,性能极差

盲读问题

  • 程序在慢速读取第一条成功后,就会开启多线程盲读,例如我将ChunkWG设定为4个线程,每次读取1条,然后我的数据库中只有2条数据
  • ChunkWG在成功读取第一条之后,从第二条开始就会进入并发读取状态,会直接无脑的并发读取第2-5页的全部数据,综上,因为3-5页的数据不存在,所以这个时候3-5条(不存在的数据)返回的空的TCP就浪费了,虽然不多但是还是浪费了
  • 如果你的数据库单表很大,SQL执行时间很长又或者不能index hit,这个时候这类的盲读就会导致数据库的CPU被浪费,并且会让你的SQL统计数据变得不好看,当然如果是简单SQL存取不费事的情况下,使用ChunkWG将会带来更多的代码性能以及解耦优势
	db := tuuz.Db().Table("bot_default_reply")
	db.Where("id", 1)
	db.ChunkWG(1, 1, func(data []gorose.Data) error {
		fmt.Println(Jsong.Encode(data))
		return nil
	})

fmt后的内容:(上下相同)

[{"id":1,"key":"帮助","value":"请使用acfurhelp来帮助"}] <nil>