MySQL查询慢别怪索引,没准是这些原因导致的( 三 )


 
当它很大时,一般常见的是下面几种情况 。
 
如果这个字段具有唯一的属性,比如电话号码等,一般是不应该有大量重复的,那可能是你代码逻辑出现了大量重复插入的操作,你需要检查下代码逻辑,或者需要加个唯一索引限制下 。
 
如果这个字段下的数据就是会很大,是否需要全部拿?如果不需要,加个limit限制下 。如果确实要拿全部,那也不能一次性全拿,今天你数据量小,可能一次取一两万都没啥压力,万一哪天涨到了十万级别,那一次性取就有点吃不消了 。你可能需要分批次取,具体操作是先用order by id排序一下,拿到一批数据后取最大id作为下次取数据的起始位置 。
 
四、连接数过小
 
索引相关的原因我们聊完了,我们来聊聊,除了索引之外,还有哪些因素会限制我们的查询速度的 。
 
我们可以看到,mysql的server层里有个连接管理,它的作用是管理客户端和mysql之间的长连接 。
 
正常情况下,客户端与server层如果只有一条连接,那么在执行sql查询之后,只能阻塞等待结果返回,如果有大量查询同时并发请求,那么后面的请求都需要等待前面的请求执行完成后,才能开始执行 。

MySQL查询慢别怪索引,没准是这些原因导致的

文章插图
 
连接过少会导致sql阻塞
 
因此很多时候我们的应用程序,比如go或JAVA这些,会打印出sql执行了几分钟的日志,但实际上你把这条语句单独拎出来执行,却又是毫秒级别的 。这都是因为这些sql语句在等待前面的sql执行完成 。
 
怎么解决呢?
 
如果我们能多建几条连接,那么请求就可以并发执行,后面的连接就不用等那么久了 。
MySQL查询慢别怪索引,没准是这些原因导致的

文章插图
 
增加连接可以加快执行sql
 
而连接数过小的问题,受数据库和客户端两侧同时限制 。
 
1、数据库连接数过小
 
Mysql的最大连接数默认是100, 最大可以达到16384 。
 
可以通过设置mysql的max_connections参数,更改数据库的最大连接数 。
 
mysql> set global max_connections= 500;Query OK, 0 rows affected (0.00 sec)mysql> show variables like 'max_connections';+-----------------+-------+| Variable_name| Value |+-----------------+-------+| max_connections | 500|+-----------------+-------+1 row in set (0.00 sec) 
上面的操作,就把最大连接数改成了500 。
 
2、应用侧连接数过小
 
数据库连接大小是调整过了,但貌似问题还是没有变化?还是有很多sql执行达到了几分钟,甚至超时?
 
那有可能是因为你应用侧(go,java写的应用,也就是mysql的客户端)的连接数也过小 。
 
应用侧与mysql底层的连接,是基于TCP协议的长链接,而TCP协议,需要经过三次握手和四次挥手来实现建连和释放 。如果我每次执行sql都重新建立一个新的连接的话,那就要不断握手和挥手,这很耗时 。所以一般会建立一个长连接池,连接用完之后,塞到连接池里,下次要执行sql的时候,再从里面捞一条连接出来用,非常环保 。
MySQL查询慢别怪索引,没准是这些原因导致的

文章插图
 
连接池原理
 
我们一般写代码的时候,都会通过第三方的orm库来对数据库进行操作,而成熟的orm库,百分之一千万都会有个连接池 。
 
而这个连接池,一般会有个大小 。这个大小就控制了你的连接数最大值,如果说你的连接池太小,都还没有数据库的大,那调了数据库的最大连接数也没啥作用 。
 
一般情况下,可以翻下你使用的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太小
 
连接数是上去了,速度也提升了 。
 
曾经遇到过面试官会追问,有没有其他办法可以让速度更快呢?
 
那必须要眉头紧锁,假装思考,然后说:有的 。
 


推荐阅读