全表扫描对server层的影响

对于查询,服务端并不是将查询的结果全部查询缓存后再发送给客户端的,而是一边读取一边发送

  1. 获取一行,写到 net_buffer 中。这块内存的大小是由参数 net_buffer_length 定义的,默认是 16k。
  2. 重复获取行,直到 net_buffer 写满,调用网络接口发出去
  3. 如果发送成功,就清空 net_buffer,然后继续取下一行,并写入 net_buffer。
  4. 如果发送函数返回 EAGAIN 或 WSAEWOULDBLOCK,就表示本地网络栈(socket send buffer)写满了,进入等待。直到网络栈重新可写,再继续发送。

所以不管查询的结果数据量有多大,对于server端来说,也就是16k大小的内存,所以根本不必在意出现爆内存的情况。

对client的影响

对于正常的线上业务来说,如果一个查询的返回结果不会很多的话,我都建议你使用 mysql_store_result 这个接口,直接把查询结果保存到本地内存。

但是如果这个查询的数据很大,那么就最好改用mysql_use_result接口。

全表扫描对InnoDB的影响

内存的数据页是在Buffer Pool中管理的,在WAL里Buffer Pool起到了加速更新的作用,而实际上,Buffer Pool还有一个更重要的作用,就是加速查询。

WAL机制保证了存在于内存当中的数据是最新的,所以事务提交的时候,如果这时候有查询立马要来读这个数据页,虽然磁盘上的数据页是旧的,但是可以直接从内存中读取,起到了加速查询的作用。

Buffer Pool对查询的加速效果,依赖于一个重要的指标,即:内存命中率

执行show engine innodb status可以查看到当前的命中率,一个线上稳定服务的系统,要保证响应时间符合要求的话,内存命中率要在99%以上。

InnoDB Buffer Pool 的大小是由参数 innodb_buffer_pool_size 确定的,一般建议设置成可用物理内存的 60%~80%。 InnoDB 内存管理用的是最近最少使用 (Least Recently Used, LRU) 算法