两表联合查询,加上排序后,效率就不高了,有没有好的优化方案

lanhai0859 2020-05-16 01:30:33
(select ctime,..... from `ni000_kline` where ctime>=1514466000 and ctime<1545980340)
UNION all
(select ctime,.....from `SR000_kline` where ctime>=1514466000 and ctime<1545980340)
order by ctime asc

需求是这样的,有两个表数据结构一直,存放的是期货不同品种的k线数据,现在需要把2018年内量表的数据都取出来写入文件,大家看看

...全文
159 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
宇峰科技 2020-05-16
  • 打赏
  • 举报
回复
select * from tt where id in

(
(select id (这是主键) from `ni000_kline` where ctime>=1514466000 and ctime<1545980340)
UNION all
(select id (这是主键) from `SR000_kline` where ctime>=1514466000 and ctime<1545980340)




查询大结果集是如何返回的:
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)算法,这个算法的核心就是淘汰最久未使用的数据。
lanhai0859 2020-05-16
  • 打赏
  • 举报
回复
两个表的数据综合110w左右,查询的数据结果是19w样子
lanhai0859 2020-05-16
  • 打赏
  • 举报
回复
ctime 是索引

56,678

社区成员

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

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