当前位置:   article > 正文

MySQL深入——23

MySQL深入——23

主机内存只有100G,现在对一个200G的大表进行扫描,会不会把数据库的内存用完。

对大表做全表扫描对Sever层的影响

假设现对一个200G的InnoDB表db1,做一个全表扫描,当然要把扫描结果保存到客户端

InnoDB的数据时保存在主键索引上的,所以全表扫描实际上是扫描表t的主键索引,最后返回给客户端。

返回的结果集并不是完整的,因为MySQL是边读边发的
流程为:1.获取一行写到net_buffer当中,net_buffer是由net_buffer_length定义的,默认为16k。

               2.重复获取知道net_buffer写满,调用网络接口发送出去。

               3.若是发送成功,就清空net_buffer,然后继续读取下一行写入net_buffer

               4.若发送函数返回EAGAIN或WSAEWOULDBLOCK就表示本地网络栈写满,直到网络栈重写可写,再继续重复操作。

一个查询在发送过程当中,占用MySQL内部最大内存就是net_buffer这么大,并不会达到200G。这意味着,若客户端接收慢,MySQL就会由于结果发送不出去导致事务执行的时间变长。

若是客户端不读socket receive buffer中的内容,然后再show processlist中可以看到state处于一个Sending to client的状态。

对于线上业务来说,若是一个查询的返回结果不会很多,就可以在客户端使用一个-quick参数就可以使用,mysql_use_result这个方法,读一行处理一行。当然前提是查询返回结果不多,若是看到多个线程都处于Sending to client,可以将net_buffer_length设置为一个更大的值。

Sending data

MySQL查询语句在进入执行阶段之后,首先将状态设置为Sending data,再继续执行语句的流程,执行完成后就会将状态改为空字符串。

也就是说在一个线程处于“等待客户端的状态”才会显示未Sending to client,Sending data是正在执行。

全表扫描对InnoDB的影响

InnoDB内存的作用是保持更新结果在配合redo log避免了随机写盘,内存的数据页是在BUffer Pool中管理的。

BUffer Pool还有一个加速功能,因为有WAL机制,当时事务要提交的时候,有一个查询要读该内存页,就可以直接读,因为这个时候,内存页是最新的,直接读内存页就可以了,无需将redo log应用到数据页当中再读取。

Buffer Pool对于查询加速效果还有一个重要的指标:内存命中率,一般情况下,内存命中率要在99%以上。

InnoDB Buffer Pool大小是由参数innodb_buffer_pool_size决定的,一般设置为物理内存的60%-80%。

innodb_buffer_pool_size小于磁盘的数据量很常见,若一个buffer pool满了,就要淘汰一个旧数据页来更新一个新数据页。InnoDB通过改进LRU算法来实现这一目标。

LRU算法:假设内存当中有P1,P2,P3,P4,P5这么多数据页,是以链表形式保存的,P1是刚刚更新的所以在头部,这个时候有请求访问P3,P3就会被移动到头部,现在要更新一个数据页,因为内存满了,要删除一个,就会删除尾巴的P5数据页。

InnoDB改进:InnoDB将其进行改进,以5:3将空间分为young和old区域,young区域中的操作和原LRU算法相同。

在old区域每次被访问的时候做如下的操作:

1.若这个数据页在LRU链表中存在时间超过1秒,就移动到头部。

2.若是短于1秒,位置保持不变

时间有参数Innodb_old_blacks_time控制,单位为毫秒,默认一秒。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/181979
推荐阅读
相关标签
  

闽ICP备14008679号