mysql> create table t1 (a int, b int);
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t1 values (1,1),(2,2);
Query OK, 2 rows affected (0.00 sec)
当执行最后一条select操作时,这里使用的类为Protocol_classic
发送metadata
ref: Protocol_classic::start_result_metadata
将列的个数写入Net缓冲区
ref: Protocol_classic::send_field_metadata
逐列的准备元数据信息,包含:
| 3bytes 标识符:def
| db_name
| table_name
| org_table_name
| col_name
| org_col_name
| 字符集编码
| 列长度
| 列类型
| flags
| decimals(这里为0)
| 预留
| 预留
可以看到每个列的元数据都包含了非常多的信息,使用字符串存储,这也意味着对于一条简单的SQL,你的网络传输的内容可能大多数都是元数据,即时你的客户端可能并不需要引用到。
有多个列就写多个packet到Net buffer (Protocol_classic::end_row)
ref: Protocol_classic::end_result_metadata
write_eof_packet函数会被调用,用于标识元数据信息到此结束。此处共写5个字节(不含packet header)
发送数据
●ref: end_send --> Protocol_classic::end_row
如上例,发送两行数据的packet包括
1
‘1’
1
‘1’
1
‘2’
1
‘2’
结束发送
ref: THD::send_statement_status -->net_send_eof --> write_eof_packet
发送结果结束标记,其中包含了sql执行过程中产生的warning个数
元数据开销
从上述可以看到,结果集中有很大一部分的开销是给元数据的,这意味着类似普通的pk查询,元数据的开销可能会非常昂贵。
以下贴下我之前测试过的一个例子,增加了几个选项来控制发送的元数据量:
0/METADATA_FULL: return all metadata, default value.
1/METADATA_REAL_COLUMN: only column name;
2/METADATA_FAKE_COLUMN: fake column name ,use 1,2...N instead of real column name
3/METADATA_NULL_COLUMN: use NULL to express the metadata information
4/METADATA_IGNORE: ignore metadata information, just for test..
测试表:
CREATE TABLE `test_meta_impact` (
`abcdefg1` int(11) NOT NULL AUTO_INCREMENT,
`abcdefg2` int(11) DEFAULT NULL,
`abcdefg3` int(11) DEFAULT NULL,
`abcdefg4` int(11) DEFAULT NULL,
……
……
`abcdefg40` int(11) DEFAULT NULL,
PRIMARY KEY (`abcdefg1`)
) ENGINE=InnoDB AUTO_INCREMENT=229361 DEFAULT CHARSET=utf8
使用mysqlslap测试并发pk查询
mysqlslap --no-defaults -uxx --create-schema=test -h$host -P $port --number-of-queries=1000000000 --concurrency=100 --query='SELECT * FROM test.test_meta_impact where abcdefg1 = 2'
测试结果
METADATA_FULL : 3.48w TPS, Net send 113M
METADATA_REAL_COLUMN: 7.2W TPS, Net send 111M
METADATA_FAKE_COLUMN: 9.2W TPS , Net send 116M
METADATA_NULL_COLUMN: 9.6w TPS , Net send 115M
METADATA_IGNORE: 13.8w TPS, Net send 30M
很显然无论网络流量还是TPS吞吐量,在这个人为构造的极端场景下,元数据的开销都非常的显著。
来源:数据库内核月
原文:http://mysql.taobao.org/monthly/2016/07/04/
如有侵权或不周之处,敬请劳烦联系若飞(微信:1321113940)马上删除,谢谢!
·END·
架构师
我们都是架构师!
架构师订阅号,关注获取更多技术分享
现已开通多个微信群,有兴趣交流学习的同学
可加若飞微信:1321113940进群
合作邮箱:admin@137x.com