mysql5.7 union all大数据量问题

linfeng763 2020-05-15 08:51:15
对mysql 5.7版本,查询用union all 后,因为大数据量,存在问题。现有几个疑问?
1. MySQL5.7执行UNION ALL不再产生临时表,那临时数据是保存在内存么?
2. 临时的中间数据如果是保存在内存,那临界点是多少大小?
3. 这个临界点是否通过MySQL的那个系统参数配置可以调整?

问题现象参考:https://blog.csdn.net/linfeng763/article/details/106123698
...全文
660 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
linfeng763 2020-05-19
  • 打赏
  • 举报
回复
调整了 innodb_buffer_pool_size,默认128M,调整256M后测试,没有问题。
不过改问题,最终采用union all调整为inner jion方式解决
宇峰科技 2020-05-16
  • 打赏
  • 举报
回复 1
查询大结果集是如何返回的:
innodb的数据是保存在主键索引上的,所以全表扫描实际是直接扫描表的主键索引。所以全扫描时查到的每一行都可以直接放到结果集里面, 然后返回客户端。
实际上,服务端并不需要保存一个完整的结果集。取数据和发数据的流程是这样的:
1、取一行,写到net_bufffer中,这块内存的大小是由参net_buffer_length定义的,默认16k。
2、重复获取行,直到net_buffer写满,调用网络接口发出去。
3、如果发送成功,就清空net_buffer,然后继续取下一行,并写入net_buffer。
4、如果发送函数返回eagain或wsaewouldblock,就表示本地网络栈(socket send buffer)写满了,进行等待。直到网络栈重新可写,再继续发送。

从流程中可以看到
1、在一个查询发送过程中,占用的mysql内部的内存最大就是net_buffer_length这么大,并不会达到20G(需要的数据大小)
2、socket send buffer也不可能达到20G(默认定义/proc/sys/net/core/wmem_default),如果socket send buffer 写满,就会暂停读数据的流程。
也就是说mysql是边读边发的。意味着,如果客户端接收的很慢会导致mysql服务端由于结果发不出去,这个事务的执行时间变长。

如果要减少处于sending to client这种状态的话,将net_buffer_length参数设置为一个更大的值是一个可选的方案。
查询语句的状态变化是这样的(略去无关状态):
1、mysql查询语句进行执行阶段后,首先把状态设置成sending data;
2、然后发送执行结果的列相关信息(meta data)给客户端
3、再继续执行语句的流程
4、执行完成后,把状态设置成空字符串。
也就是说 sending data并不一定是指正在发送数据,而可能是处于执行器过程中的任意阶段。
仅当一个线程片于等待客户端接收结果的状态,才会显示sending to client,而如果显示sending data意思只是正在执行。
innodb_buffer_pool_size一般建议设置为可用物理内存的60%或80%。
inndob内存管理用的是最近最少使用算法(Least Recently Used,LRU)算法,这个算法的核心就是淘汰最久未使用的数据。

56,679

社区成员

发帖
与我相关
我的任务
社区描述
MySQL相关内容讨论专区
社区管理员
  • MySQL
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧