Mysql数据库查询好慢,除了索引,还能因为什么?( 四 )


一般情况下,可以翻下你使用的orm库的文档,看下怎么设置这个连接池的大小,就几行代码的事情,改改就好 。比如Go语言里的gorm里是这么设置的
func Init() {  db, err := gorm.Open(mysql.Open(conn), config)    sqlDB, err := db.DB()    // SetMaxIdleConns 设置空闲连接池中连接的最大数量    sqlDB.SetMaxIdleConns(200)    // SetMaxOpenConns 设置打开数据库连接的最大数量    sqlDB.SetMaxOpenConns(1000)} 
buffer pool太小连接数是上去了,速度也提升了 。
曾经遇到过面试官会追问,有没有其他办法可以让速度更快呢?
那必须要眉头紧锁,假装思考,然后说:有的 。
我们在前面的数据库查询流程里,提到了进了innodb之后,会有一层内存buffer pool,用于将磁盘数据页加载到内存页中,只要查询到buffer pool里有,就可以直接返回,否则就要走磁盘IO,那就慢了 。
也就是说,如果我的buffer pool 越大,那我们能放的数据页就越多,相应的,sql查询时就更可能命中buffer pool,那查询速度自然就更快了 。
可以通过下面的命令查询到buffer pool的大小,单位是Byte 。
mysql> show global variables like 'innodb_buffer_pool_size';+-------------------------+-----------+| Variable_name           | Value     |+-------------------------+-----------+| innodb_buffer_pool_size | 134217728 |+-------------------------+-----------+1 row in set (0.01 sec)也就是128Mb 。
如果想要调大一点 。可以执行
mysql> set global innodb_buffer_pool_size = 536870912;Query OK, 0 rows affected (0.01 sec)mysql> show global variables like 'innodb_buffer_pool_size';+-------------------------+-----------+| Variable_name           | Value     |+-------------------------+-----------+| innodb_buffer_pool_size | 536870912 |+-------------------------+-----------+1 row in set (0.01 sec)这样就把buffer pool增大到512Mb了 。
但是吧,如果buffer pool大小正常,只是别的原因导致的查询变慢,那改buffer pool毫无意义 。
但问题又来了 。
 
怎么知道buffer pool是不是太小了?这个我们可以看buffer pool的缓存命中率 。

Mysql数据库查询好慢,除了索引,还能因为什么?

文章插图
 
查看buffer pool命中率
通过 show status like 'Innodb_buffer_pool_%';可以看到跟buffer pool有关的一些信息 。
Innodb_buffer_pool_read_requests表示读请求的次数 。
Innodb_buffer_pool_reads 表示从物理磁盘中读取数据的请求次数 。
所以buffer pool的命中率就可以这样得到:
buffer pool 命中率 = 1 - (Innodb_buffer_pool_reads/Innodb_buffer_pool_read_requests) * 100%比如我上面截图里的就是,1 - (405/2278354) = 99.98% 。可以说命中率非常高了 。
一般情况下buffer pool命中率都在99%以上,如果低于这个值,才需要考虑加大innodb buffer pool的大小 。
当然,还可以把这个命中率做到监控里,这样半夜sql变慢了,早上上班还能定位到原因,就很舒服 。
 
还有哪些骚操作?前面提到的是在存储引擎层里加入了buffer pool用于缓存内存页,这样可以加速查询 。
那同样的道理,server层也可以加个缓存,直接将第一次查询的结果缓存下来,这样下次查询就能立刻返回,听着挺美的 。
按道理,如果命中缓存的话,确实是能为查询加速的 。但这个功能限制很大,其中最大的问题是只要数据库表被更新过,表里面的所有缓存都会失效,数据表频繁的更新,就会带来频繁的缓存失效 。所以这个功能只适合用于那些不怎么更新的数据表 。
另外,这个功能在8.0版本之后,就被干掉了 。所以这功能用来聊聊天可以,没必要真的在生产中使用啊 。
Mysql数据库查询好慢,除了索引,还能因为什么?

文章插图
 
查询缓存被删除
 
总结