MySQL5.7 union all 大数据量问题

问题现象

数据库有3张表,如chinese_score、math_score、english_score,分别代表学生的语文成绩、数学成绩、英语成绩,每张表的表结构和数据量一致,200万数据量。表结构如下:

ID(主键)code(学号)name(姓名)score(成绩)

执行的SQL(获得每个学生的总成绩):

select code, name, sum(t.score) total_score
from
    (
        select code, name, score from chinese_score
        union all
        select code, name, score from math_score
        union all
        select code, name, score from english_score
    ) t
group by code,name

运行结果
MySQL5.6中运行,结果total_score合计正常
MySQL5.7中运行,结果total_score的值为语文的成绩,没有合计3个总成绩
即如结果中,查看张三的总成绩(语文90、数学85、英语100),5.6版本总成绩为275,5.7版本为90

这么坑,它也没有报错,直接数据不对

解决问题

网上查找资料,发现有篇文章说到MySQL5.7之后对union all有更新:

MySQL在以下几种情况会创建临时表:
UNION查询(MySQL 5.7起,执行UNION ALL不再产生临时表,除非需要额外排序。);

本来union all查询是中间产生临时表的,但是MySQL 5.7不产生临时表了,估计数据在内存了,然后估计数据量超出其限制了,就丢弃后面数据了(只是猜测)

因为我测试过每个150万数据量没有问题,而两个160万就不对了

select code, name, sum(t.score) total_score
from
    (
        select code, name, score from chinese_score order by code limit 1500000
        union all
        select code, name, score from math_score order by code limit 1500000
        union all
        select code, name, score from english_score order by code limit 1500000
    ) t
group by code,name
select code, name, sum(t.score) total_score
from
    (
        select code, name, score from chinese_score order by code limit 1600000
        union all
        select code, name, score from math_score order by code limit 1600000
    ) t
group by code,name

所以最终解决方法就是修改SQL,添加排序

select code, name, sum(t.score) total_score
from
    (
        select code, name, score from chinese_score
        union all
        select code, name, score from math_score
        union all
        select code, name, score from english_score
        order by code
    ) t
group by code,name

添加了 order by code
这样5.6和5.7运行都是正确的

问题疑问

  1. MySQL5.7执行UNION ALL不再产生临时表,那临时数据是保存在内存么?
  2. 临时的中间数据如果是保存在内存,那临界点是多少大小?
  3. 这个临界点是否通过MySQL的那个系统参数配置可以调整?

不知道哪位大神可以救救小弟,不胜感激。

测试

  1. 调整了 innodb_buffer_pool_size,默认128M,调整256M后测试,可以问题,因此跟innodb_buffer_pool_size存在关系
  2. 终采用union all调整为inner jion方式就不会涉及该问题
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值