背景
为了实验需求,我们需要快速生成一张平均行长较大的表。计划生成名为 aaa.tab1 的表,该表的平均行长约为 20K,包含 100 万行,预计生成约 20GB 的 CSV 文件。
工具下载和使用
- 安装下载工具说明 https://github.com/kennytm/dbgen/blob/master/Download.md
- 保存 t.sql
注:在实际开发中,不推荐使用复杂的数据类型,如TEXT、BLOB类型。然而,为了方便构造宽表,我在此使用了 多个 TEXT 字段;为了确定性的行长,用了定长的 char。
CREATE TABLE `aaa`.`TAB1` (
`a` varchar(32) NOT NULL COMMENT '' /*{{ mod(rownum+0,100) || rand.regex('[0-9a-zA-Z]{30}') }}*/,
`b` varchar(32) NOT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{32}') }}*/,
`c` varchar(32) NOT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{32}') }}*/,
`d` varchar(10) DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{10}') }}*/,
`e` varchar(2) DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{2}') }}*/,
`f` varchar(5) DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{5}') }}*/,
`g` varchar(4) DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{4}') }}*/,
`h` varchar(4) DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{4}') }}*/,
`i` varchar(4) DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{4}') }}*/,
`j` text DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{6200}') }}*/,
`k` text DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{6200}') }}*/,
`l` text DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{6200}') }}*/,
`m` varchar(4) DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{4}') }}*/,
`n` varchar(5) DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{5}') }}*/,
`o` text DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{510}') }}*/,
`p` varchar(7) DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{7}') }}*/,
`q` varchar(500) DEFAULT NULL COMMENT '' /*{{ rand.regex('[0-9a-zA-Z]{500}') }}*/,
`r` int(11) DEFAULT NULL COMMENT '' /*{{ rand.range_inclusive(0,2147483647) }}*/,
`s` datetime NOT NULL COMMENT '' /*{{ current_timestamp - INTERVAL rand.range_inclusive(0, 86400*30) SECOND + INTERVAL rand.range_inclusive(0,999999) MICROSECOND }}*/,
`t` datetime NOT NULL COMMENT '' /*{{ current_timestamp - INTERVAL rand.range_inclusive(0, 86400*30) SECOND + INTERVAL rand.range_inclusive(0,999999) MICROSECOND }}*/,
PRIMARY KEY(`a`),
INDEX `IDX_t`(`t`)
)
ENGINE = InnoDB DEFAULT CHARACTER SET = UTF8MB4 DEFAULT COLLATE = UTF8MB4_BIN COMMENT = '';
-
运行
- -R是每个 csv 多少行
- -N 是一共多少行,所以 csv 文件数量=N/R
./dbgen -i ./t.sql -f csv -R 15000 -N 1000000 -o ./output
这个估算的 CSV 文件体积非常准确。在生成 CSV 的初期,瞬时速度较高,基本可以使磁盘 IO 达到饱和。在我这台配备普通 SSD 的云主机上,大约一分钟即可生成 19GB 的 CSV 文件。
[tidb@vm172-16-201-22 bin]$ ./dbgen -i ./t.sql -f csv -R 15000 -N 1000000 -o ./output
Using seed: 3ce68633d40ae080e51b29e74cd5367468c062bfb294c6fb8c2a1cdff2efff67
Done!
Size 18.50 GB / 18.50 GB 🕛 291.21 MB/s
[tidb@vm172-16-201-22 bin]$ du -sh output/
19G output/
导入 csv
vim tidb-lightning.toml
[lightning]
# 转换数据的并发数,默认为逻辑 CPU 数量,不需要配置。
# 混合部署的情况下可以配置为逻辑 CPU 的 75% ⼤⼩。
# region-concurrency =
# ⽇志
level = "info"
file = "tidb-lightning.log"
[tikv-importer]
# backend 设置为 local 模式
backend = "local"
# 设置排序的键值对的临时存放地址,⽬标路径需要是⼀个空⽬录
sorted-kv-dir = "/data/tmp/sorted-kv-dir"
[checkpoint]
# 启⽤断点续传。
# 导⼊时,TiDB Lightning 会记录当前进度。
# 若 TiDB Lightning 或其他组件异常退出,在重启时可以避免重复再导⼊已完成的数据。
enable = true
# 存储断点的⽅式
# - file:默认存储路径为 /tmp/CHECKPOINT_SCHEMA.pb
driver = "file"
[mydumper]
# Mydumper 源数据⽬录。
data-source-dir = "/home/tidb/bin/output"
filter = ['aaa.*'] #只导⼊这些库
[mydumper.csv]
header = false
[tidb]
# ⽬标集群的信息。tidb-server 的监听地址,填⼀个即可。
host = "172.16.201.22"
port = 4000
user = "root"
password = ""
# 表架构信息在从 TiDB 的“状态端⼝”获取。
status-port = 10080
# pd-server 的地址,填⼀个即可
pd-addr = "172.16.201.22:2379"
[post-restore]
analyze = "off" #如果要快速导入,这个值设为off,导入完成后再手工收集统计信息
checksum = "required"
导入命令
nohup ./tidb-lightning -config tidb-lightning.toml --check-requirements=false > nohup.out &
收集统计信息
# 宽表一般是通过定制策略来收集的,后续的 auto analyze 将继承该策略
analyze table aaa.TAB1 columns a, t with 110000 samples , 256 BUCKETS, 300 TOPN;
附录
常用的字段类型提示
字段类型 |
提示表达式 |
int |
##为方便测试,通常不造数负数 /*{{ rand.range_inclusive(0,2147483647) }}*/ |
char(32) |
/*{{ rand.regex('[0-9a-zA-Z]{32}') }}*/ |
varchar(32) |
/*{{ rand.regex('[0-9a-zA-Z]{1,32}') }}*/ |
decimal(20,3) |
/*{{ rand.regex('[0-9]{1,17}\.[0-9]{3}') }}*/ |
datetime |
/*{{ current_timestamp - INTERVAL rand.range_inclusive(0, 86400*30) SECOND + INTERVAL rand.range_inclusive(0,999999) MICROSECOND }}*/ |