写点什么

TiDB 的平面文件与数据体积

  • 2024-05-24
    北京
  • 本文字数:3439 字

    阅读完需:约 11 分钟

作者: Jayjlchen 原文来源:https://tidb.net/blog/a55941b1

背景

用户在使用 4.0.14 版本进行数据库迁移时,发现通过 dumpling 导出的全量备份体积为 3.5T,而每个 TiKV 节点分别占用 1.36T 的存储空间,总共占用了 4.08T 的空间。用户想了解导出的 CSV 文件的体积应该如何估算,并且为什么导出的单副本 CSV 文件体积接近整个集群的体积。

说明

下面用实验来说明平面文件与数据体积相关的关系:


sysbench 造数 10 张表。


sysbench --config-file=tidb_config oltp_read_write --tables=10 --table-size=2000000 --db-ps-mode=auto --rand-type=uniform --mysql-ignore-errors=2013 prepare
复制代码


根据官网的“如何预估 TiDB 中的一张表的大小”,我们可以查到表的压缩前和压缩后的体积。


https://docs.pingcap.com/zh/tidb/v6.5/manage-cluster-faq#%E5%A6%82%E4%BD%95%E9%A2%84%E4%BC%B0-tidb-%E4%B8%AD%E4%B8%80%E5%BC%A0%E8%A1%A8%E7%9A%84%E5%A4%A7%E5%B0%8F


SELECT    db_name,    table_name,    ROUND(SUM(total_size / cnt), 2) Approximate_Size,    ROUND(SUM(total_size / cnt / (SELECT                    ROUND(AVG(value), 2)                FROM                    METRICS_SCHEMA.store_size_amplification                WHERE                    value > 0)),            2) Disk_SizeFROM    (SELECT        db_name,            table_name,            region_id,            SUM(Approximate_Size) total_size,            COUNT(*) cnt    FROM        information_schema.TIKV_REGION_STATUS    WHERE        db_name = 'sbtest'    GROUP BY db_name , table_name , region_id) tabinfoGROUP BY db_name , table_name;
#sum(Approximate_Size)是 6.18 GB#sum(Disk_Size)是 3.93 GB+---------+------------+------------------+-----------+| db_name | table_name | Approximate_Size | Disk_Size |+---------+------------+------------------+-----------+| sbtest | sbtest5 | 609.00 | 392.90 || sbtest | sbtest6 | 631.00 | 407.10 || sbtest | sbtest9 | 699.00 | 450.97 || sbtest | sbtest4 | 711.00 | 458.71 || sbtest | sbtest3 | 712.00 | 459.35 || sbtest | sbtest2 | 597.00 | 385.16 || sbtest | sbtest8 | 597.00 | 385.16 || sbtest | sbtest10 | 711.00 | 458.71 || sbtest | sbtest1 | 593.00 | 382.58 || sbtest | sbtest7 | 728.00 | 469.68 |+---------+------------+------------------+-----------+10 rows in set (0.01 sec)
复制代码


在 grafana 的 <tidb-cluster>-PD 的 Statistics-balance 面板的 Store used 、Store Region size、Size amplification 也可以观察到。



Store Region size 可以理解为“压缩前的体积”;


Store used 可以理解为“压缩后的体积”;


Size amplification 是“压缩比平均值”。


Store used ≈ Store Region size / Size amplification


注:本实验的数据体积过小,没有多少压缩比可言。TiDB 默认的层级压缩参数为compression-per-level = ["no", "no", "lz4", "lz4", "lz4", "zstd", "zstd"], 在数据量大时,压缩比高。


导出的 CSV 体积是否等于 “Store Region size 总和 / 3 (副本)” 呢?


不是的。CSV 导入到 TiDB 后,转换为 region 的体积会有所放大。此外,还需要考虑索引大小的影响,因此 Store Region size 通常会显得偏大。


导出的 CSV 文件实际上是单一副本,不包含索引数据量,可以理解为略大于 DATA_LENGTH 的总和。


为什么说是大于 DATA_LENGTH 总和呢?


由于 DATA_LENGTH 的计算依赖于数据库的统计信息,而实际情况中,数据库中常常存在统计信息尚未被收集或已经过时,但尚未达到自动触发 auto analyze 操作的标准的情况。


验证过程:


################ 1.CSV 体积基本等于 DATA_LENGTH 总和的情况 ######################## #数据是 sysbench insert 而来,会自动触发统计信息收集MySQL [(none)]> select table_schema,sum(DATA_LENGTH)/1024/1024/1024 from information_schema.tables where TABLE_SCHEMA = 'sbtest' group by table_schema;+--------------+---------------------------------+| table_schema | sum(DATA_LENGTH)/1024/1024/1024 |+--------------+---------------------------------+| sbtest       |                  3.764550373890 |+--------------+---------------------------------+1 row in set (0.01 sec)
nohup ./dumpling \ -u root \ -P 4000 \ -h 172.16.201.22 \ -t 8 \ -o /data/backup \ -r 200000 \ -F 256MiB \ --filetype csv \ -B sbtest > nohup.out & [tidb@vm172-16-201-22 backup]$ du -sh3.8G
# 表的平均行长为 199 bytes,抽样验证导出的 CSV 文件也是每行 199 bytes 左右。MySQL [(none)]> select TABLE_NAME,AVG_ROW_LENGTH from information_schema.tables where table_schema='sbtest' AND table_name='sbtest1';+------------+----------------+| TABLE_NAME | AVG_ROW_LENGTH |+------------+----------------+| sbtest1 | 199 |+------------+----------------+1 row in set (0.01 sec)
[tidb@vm172-16-201-22 backup]$ lines=$(wc -l < sbtest.sbtest1.0000000000000.csv)[tidb@vm172-16-201-22 backup]$ bytes=$(wc -c < sbtest.sbtest1.0000000000000.csv)[tidb@vm172-16-201-22 backup]$ avg_line_length=$(echo "scale=2; $bytes / $lines" | bc)[tidb@vm172-16-201-22 backup]$ echo "Average line length: $avg_line_length bytes"Average line length: 198.84 bytes

################ 2.CSV 体积大于 DATA_LENGTH 总和的情况 ######################## #数据是 lightning 设置 analyze = "off" 导入的,缺失统计信息mysql> select DATA_LENGTH from information_schema.tables where table_name='sbtest1';+-------------+| DATA_LENGTH |+-------------+| 0 |+-------------+1 row in set (0.01 sec)
#lightning local 模式导入,Modify_count 和 Row_count 会为 0,所以也不会自动触发统计信息收集 mysql> show stats_meta where table_name='sbtest1';+---------+------------+----------------+---------------------+--------------+-----------+| Db_name | Table_name | Partition_name | Update_time | Modify_count | Row_count |+---------+------------+----------------+---------------------+--------------+-----------+| sbtest | sbtest1 | | 2024-05-21 20:43:12 | 0 | 0 |+---------+------------+----------------+---------------------+--------------+-----------+1 row in set (0.00 sec)
#不能用健康度判断统计信息是否准确,即使是新建一张空表,没收集统计信息时,也显示 100mysql> show stats_healthy where table_name='sbtest1';+---------+------------+----------------+---------+| Db_name | Table_name | Partition_name | Healthy |+---------+------------+----------------+---------+| sbtest | sbtest1 | | 100 |+---------+------------+----------------+---------+1 row in set (0.00 sec)
mysql> select count(*) from sbtest1;+----------+| count(*) |+----------+| 2000000 |+----------+1 row in set (0.51 sec)
复制代码

用户验证

导出的 CSV 大小等于 DATA_LENGTH 的总和。



后话

估算导出的 CSV 平面文件的体积相对容易。但如果要估算 CSV 文件导入后的体积,这就比较困难了。因为每个行业的数据特点不同,压缩率也会有所差异。举个不严谨的例子,一亿条相同的数据,压缩后可能只占用一条的空间。较为精确的估算方法是,先导入 10% 的 CSV 文件,然后根据观察到的体积来估算最终的导入体积。


如果一定要给出一个经验比例值,那么大致可以认为 3T 的 CSV 文件导入后会占用 4.5 至 6T 的存储空间(包括三副本),就算宽裕估算比值也是 1 : 2 的关系。相比于 MySQL 三副本使用的数据体积,这个压缩率已经相当可观。


发布于: 刚刚阅读数: 1
用户头像

TiDB 社区官网:https://tidb.net/ 2021-12-15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
TiDB 的平面文件与数据体积_管理与运维_TiDB 社区干货传送门_InfoQ写作社区