【 TiDB 使用环境】Poc
【 TiDB 版本】5.7.25-TiDB-v6.5.2
修改tidb_max_paging_size=256,tidb_distsql_scan_concurrency=1其余参数默认
这种情况下执行:select a.* from a;观察内存使用比预想的要大。
预想的内存占用:
为了模拟上层算子执行缓慢让distsql请求返回的RPC请求积压,这里直接修改了tidb-server的源代码,将explain analyze部分进行了延迟处理,让tikv-client的消息更容易积。
tidb/executor/explain.go at 29116c0256c52b224da2b34d712c1063d171c0ad · pingcap/tidb · GitHub
在上面这里的每一次循环获取结果集时候做time.Sleep(time.Second) 延迟处理。
让tikv返回的RPC消息进行堆积,在内存占用最大情况下(基本只有tikv-client堆积消息占用内存)为:tidb_distsql_scan_concurrency * tidb_max_paging_size * 表所有字段定义大小之和
我想内存占用不应该超过上面这个预想值,但是实际上内存占用却比这个要大挺多(感觉copTask请求执行完返回tikv-client缓存的数目远比tidb_distsql_scan_concurrency 大)。
具体场景:
表结构定义:
mysql> desc lineitem_bak;
+-----------------+---------------+------+------+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------+------+------+---------+-------+
| L_ORDERKEY | bigint(20) | NO | PRI | NULL | |
| L_PARTKEY | bigint(20) | NO | | NULL | |
| L_SUPPKEY | bigint(20) | NO | | NULL | |
| L_LINENUMBER | bigint(20) | NO | PRI | NULL | |
| L_QUANTITY | decimal(15,2) | NO | | NULL | |
| L_EXTENDEDPRICE | decimal(15,2) | NO | | NULL | |
| L_DISCOUNT | decimal(15,2) | NO | | NULL | |
| L_TAX | decimal(15,2) | NO | | NULL | |
| L_RETURNFLAG | char(1) | NO | | NULL | |
| L_LINESTATUS | char(1) | NO | | NULL | |
| L_SHIPDATE | date | NO | MUL | NULL | |
| L_COMMITDATE | date | NO | | NULL | |
| L_RECEIPTDATE | date | NO | | NULL | |
| L_SHIPINSTRUCT | char(25) | NO | | NULL | |
| L_SHIPMODE | char(10) | NO | | NULL | |
| L_COMMENT | varchar(44) | NO | | NULL | |
| col1 | decimal(15,2) | YES | | NULL | |
| col2 | decimal(15,2) | YES | | NULL | |
| col3 | decimal(15,2) | YES | | NULL | |
| col4 | decimal(15,2) | YES | | NULL | |
| col5 | decimal(15,2) | YES | | NULL | |
| col6 | decimal(15,2) | YES | | NULL | |
| col7 | decimal(15,2) | YES | | NULL | |
| col8 | decimal(15,2) | YES | | NULL | |
| col9 | decimal(15,2) | YES | | NULL | |
| col10 | decimal(15,2) | YES | | NULL | |
| col11 | decimal(15,2) | YES | | NULL | |
| col12 | decimal(15,2) | YES | | NULL | |
| col13 | decimal(15,2) | YES | | NULL | |
| col14 | decimal(15,2) | YES | | NULL | |
| col15 | decimal(15,2) | YES | | NULL | |
| col16 | decimal(15,2) | YES | | NULL | |
| col17 | decimal(15,2) | YES | | NULL | |
| col18 | decimal(15,2) | YES | | NULL | |
| col19 | decimal(15,2) | YES | | NULL | |
| col20 | decimal(15,2) | YES | | NULL | |
| col21 | decimal(15,2) | YES | | NULL | |
| col22 | decimal(15,2) | YES | | NULL | |
| col23 | decimal(15,2) | YES | | NULL | |
| col24 | decimal(15,2) | YES | | NULL | |
| col25 | decimal(15,2) | YES | | NULL | |
| col26 | decimal(15,2) | YES | | NULL | |
| col27 | decimal(15,2) | YES | | NULL | |
| col28 | decimal(15,2) | YES | | NULL | |
| col29 | decimal(15,2) | YES | | NULL | |
| col30 | decimal(15,2) | YES | | NULL | |
| col31 | decimal(15,2) | YES | | NULL | |
| col32 | decimal(15,2) | YES | | NULL | |
| col33 | decimal(15,2) | YES | | NULL | |
| col34 | decimal(15,2) | YES | | NULL | |
| col35 | decimal(15,2) | YES | | NULL | |
| col36 | decimal(15,2) | YES | | NULL | |
| col37 | decimal(15,2) | YES | | NULL | |
| col38 | decimal(15,2) | YES | | NULL | |
| col39 | decimal(15,2) | YES | | NULL | |
| col40 | decimal(15,2) | YES | | NULL | |
| col41 | decimal(15,2) | YES | | NULL | |
| col42 | decimal(15,2) | YES | | NULL | |
| col43 | decimal(15,2) | YES | | NULL | |
| col44 | decimal(15,2) | YES | | NULL | |
| col45 | decimal(15,2) | YES | | NULL | |
| col46 | decimal(15,2) | YES | | NULL | |
| col47 | decimal(15,2) | YES | | NULL | |
| col48 | decimal(15,2) | YES | | NULL | |
| col49 | decimal(15,2) | YES | | NULL | |
| col50 | decimal(15,2) | YES | | NULL | |
+-----------------+---------------+------+------+---------+-------+
66 rows in set (0.00 sec)
表数据量和语句执行计划:
mysql> select count(*) from lineitem_bak;
+-----------+
| count(*) |
+-----------+
| 179998372 |
+-----------+
1 row in set (16.14 sec)
mysql> explain select * from lineitem_bak;
+-----------------------+--------------+-----------+--------------------+----------------------+
| id | estRows | task | access object | operator info |
+-----------------------+--------------+-----------+--------------------+----------------------+
| TableReader_5 | 179998372.00 | root | | data:TableFullScan_4 |
| └─TableFullScan_4 | 179998372.00 | cop[tikv] | table:lineitem_bak | keep order:false |
+-----------------------+--------------+-----------+--------------------+----------------------+
2 rows in set (0.00 sec)
--设置参数:
mysql> set tidb_distsql_scan_concurrency=1;
Query OK, 0 rows affected (0.00 sec)
mysql> set tidb_max_paging_size=256;
Query OK, 0 rows affected (0.00 sec)
--发起语句执行:
mysql> explain analyze select * from lineitem_bak;
等待至少20秒,让tikv数据充分返回给tidb-server进行积压,观察processlist情况:
mysql> select * from information_schema.processlist\G
*************************** 1. row ***************************
ID: 4050963675563950485
USER: root
HOST: 192.168.31.200:42902
DB: tpch
COMMAND: Query
TIME: 120
STATE: autocommit
INFO: explain analyze select * from lineitem_bak
DIGEST: 474e5e529400b26f8147ce06f488416d9e5f948c01deb9f0244de806fd5438bf
MEM: 231428128
DISK: 0
TxnStart: 06-11 10:03:22.584(442092487333380097)
*************************** 2. row ***************************
ID: 4050963675563950487
USER: root
HOST: 192.168.31.200:49006
DB: tpch
COMMAND: Query
TIME: 0
STATE: autocommit
INFO: select * from information_schema.processlist
DIGEST: 4b5e7cdd5d3ed84d6c1a6d56403a3d512554b534313caf296268abdec1c9ea99
MEM: 0
DISK: 0
TxnStart:
2 rows in set (0.00 sec)
因为lineitem_bak表一共66个字段,每一个字段占用的内存最大不超过L_COMMENT varchar(44),所以每一行记录最大不会超过66 * 44 = 2904字节,加上内存操作其它占位符等平均每行内存使用不会超过3000字节。
预计内存整体占用为:
tidb_distsql_scan_concurrency * tidb_max_paging_size * 表所有字段定义大小之和 = 1 * 256 * 3000 = 768000字节 约为(750KB)。
但是实际上内存占用了231428128字节约为(230MB),远远大于预估的内存量。
heap信息:
所以tidb_enable_paging=ON的情况下内存占用为何还是较大呢?
是否除tidb_distsql_scan_concurrency之外还有其它并发条件?