这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战.
实现
Sysbench is a benchmark suite which allows you to quickly get an impression of system performance which is important if you plan to run a database under intensive load.
sysbench 是一个常用的负载测试套装,bulk_insert 是其中用于对数据库进行批量写入的测试 lua。
执行 sysbench 测试用例需要用户执行 prepare 和 run 命令,prepare 时调用一次测试 lua 中的 prepare 函数,run 时不断调用测试 lua 中的 event 函数。
在 bulk_insert 中,prepare 负责在目标数据库建好 threads 张表,表名分别是 sbtest1, sbtest2, ...
bulk_insert 的 run 命令包含了以下部分:
- 全局变量 cursize 初始为 0
- 调用 bulk_insert_init("insert into sbtest1 values")
- 每次 event,cursize++,调用 bulk_insert_next("(cursize,cursize)")
- 当测试结束时,调用 bulk_insert_done.
第一反应内部的执行逻辑是这样的:内建函数 init 和 next 完成了类似于查询字符串拼接的工作,done 时实际提交查询。
但如果是这样,整个线程运行过程只会执行一次查询,与预期结果不符。
查阅实现代码得知,bulk_insert_next 时如果发现当前查询字符串长度大于了预设的常数 con->bulk_buflen 也就是 BULK_PACKET_SIZE 也就是 512*1024 也就是 524288,就会将当前查询执行掉,然后从头开始拼接字符串。
改造
我的需求有两个:
- 让单次 query 的插入条数固定。 bulk_insert 单次执行的插入条数不是固定的,而是会随着 cur_size 变大,数据长度变大,单次 query 的数据量越来越少,初始时约为 39000,之后稳定在 33000+.
- 在查询字符串的数据部分结束后,写一些字符,如
on conflict do nothing.
这些都可以通过手动控制提交时间来实现:
function event()
if (cursize % 10000 ~= 0) then
con:bulk_insert_next("(" .. 10000000+cursize .. "," .. 10000000+cursize .. ")")
elseif (cursize ~= 0) then
con:bulk_insert_next("(" .. 10000000+cursize .. "," .. 10000000+cursize .. ")")
con:bulk_insert_done()
con:bulk_insert_init("INSERT INTO sbtest" .. sysbench.tid+1 .. " VALUES")
else
con:bulk_insert_init("INSERT INTO sbtest" .. sysbench.tid+1 .. " VALUES")
end
cursize = cursize + 1
end
function thread_done()
con:bulk_insert_done()
con:disconnect()
end
小声 bb
其实完全可以自己写个 lua 实现,为什么要用 bulk_insert 呢?主要是因为好奇 bulk_insert 的实现,以及懒得查语法(
为什么这些 c 语言项目不用 cpp 写啊,看代码看到手动虚表真的很不友好。
为什么会有 3 空格缩进的代码(
本文也发表于我的 csdn 博客中。