全表扫描对server层的影响
对于查询,服务端并不是将查询的结果全部查询缓存后再发送给客户端的,而是一边读取一边发送。
- 获取一行,写到 net_buffer 中。这块内存的大小是由参数 net_buffer_length 定义的,默认是 16k。
- 重复获取行,直到 net_buffer 写满,调用网络接口发出去。
- 如果发送成功,就清空 net_buffer,然后继续取下一行,并写入 net_buffer。
- 如果发送函数返回 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) 算法