是不是经常会听到有人吐槽查询有多慢,娃都出来了,系统还是这么慢,系统查询慢一般情况下和数据库的查询性能有很大的关系,这也是绿叶君面试时比较喜欢聊的话题,本篇文章简单总结了一下可能导致数据库查询慢的原因,希望能给大家后续查询优化提供一下指导。

数据存储结构不合理

一般关系型数据库的物理存储分为堆和B+树,一般索引的存储结构为B+树,而数据表如果没有建立聚集索引的话,数据就是堆存储。这两种存储结构会很大程度上印象查询效率,B+树可以按照Key进行定向查找,而堆只能逐行扫描。这就像去图书馆找一本书,通过索引号可以快速找到其位置,而从书架上一排排看过去效率就很低。

这里需要说明一下,并非B+树的存储结构永远比堆存储结构好,至于什么情况下适合用堆存储,大家可以讨论一下。

查找效率低

查找效率还会受列存储和行存储的影响,列存储是按照表格中的同一列数据一起存储,而行存储是把表格中的数据一行一行的一起存储,这两种存储方式也会对查找效率造成影响。

磁盘IO过高

一般查询引擎都是按照数据块读取,只要某个数据块中有需要的数据,那么就会把这个数据块读取到内存中,所以如果数据过于分散,也会很大程度上影响查询效率,表现为磁盘IO很高。这方面涉及到索引碎片,索引重建,索引整理等技术。

另外数据的压缩比也会影响到磁盘的IO,理论上压缩比越高,数据读取的效率越高,相同情况下磁盘IO会低很多,但是数据压缩意味着存储时需要压缩,读取后需要解压,所以需要综合考虑,并非压缩比越高越好。

查询等待时间过长

有时候分析查询过程会发现,执行耗时很短,反而大部分时间都在排队,这种现象在多产品共用一个查询平台时最容易出现(请允许我先哭上三分钟......),导致这种情况一般是系统资源不足(内存不足等),导致无法为查询分配足够的资源执行。

查询等待还经常会因为锁等待导致,也就是当我想查这行数据时,其他人正在对这行数据进行编辑(排它锁),这时候我就需要等对方编辑完成才能读取。这方面根据实际场景可以考虑脏读等方式。

网络传输原因

数据在服务器端查询完成之后一般都需要通过网络传输到客户端,这时候如果一次返回的数据量过大,也会导致用户感觉查询变慢,这种情况需要应用端进行分页处理,或者对数据进行压缩传输。

执行计划不合理

因为索引碎片过大或者统计信息缺失等原因会造成数据库的查询引擎生成一些不够合理的查询计划,这时候推荐的做法是重建索引或者更新统计信息,当然也可以使用hint的方式强制更改查询计划,但这种方式很容易遗忘,引发后续其他情况下的查询问题。

系统资源不足或者被抢占

现在一般服务器都是采用虚拟化的技术进行资源隔离,但是很多虚拟化技术无法控制CPU的隔离,所以如果其他应用占用了大量CPU资源可能会导致数据库查询慢。

数据库的查询操作一般都现在内存中查找是否缓存了相应数据,如果没有则需要先把数据读取到内存中,这就导致了,当内存过低时,会造成查询命中率很低,需要频繁的到磁盘中读取数据,从而影响数据库的查询性能。

数据库是高内存,高IO,高CPU的应用,所以一般推荐一个物理机上不要开多个数据库服务器,避免相互抢占资源。

硬件配置不足

上面提到,数据库是高内存,高IO,高CPU的应用,所以服务器的硬件配置如果不够也会很大程度上影响数据库的查询性能,一般数据库应用都会对服务器的硬件配置有一定的要求,大家可以在安装时检查。

以上虽然没有涉及具体的优化操作方式,但相信大家理解了原理之后,无论应对哪种数据库查询优化场景都可以找到思路。