0
0
0
0
专栏/.../

TiDB 的平面文件与数据体积

 Jayjlchen  发表于  2024-05-21

背景

用户在使用 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_Size
FROM
    (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) tabinfo
GROUP 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 -sh
3.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)

#不能用健康度判断统计信息是否准确,即使是新建一张空表,没收集统计信息时,也显示 100
mysql> 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 三副本使用的数据体积,这个压缩率已经相当可观。

0
0
0
0

版权声明:本文为 TiDB 社区用户原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接和本声明。

评论
暂无评论