作为后端开发工程师,无论是在哪家公司,哪个团队,或者是做哪个系统,数据库性能问题绝对是第一个让人头疼的问题,因为数据库性能优化是项目实施过程中必须要做的事情,加之每个项目不同,对其数据的要求、性能压力也不同,如果有一套成熟的方法论,能让大家快速、准确的去选择合适的优化方案,我相信大家就能够快速解决日常遇到的80%-90%的性能问题。
解决问题,首先就需要了解问题的原因,其次再有一套思考、判断问题的流程方式,让我们合理的站在某个层面上去选择方案,最后从众多的方案里选择一个合适的方案解决问题,但在找到一个合适方案的前提是我们自己对各种方案之间的优缺点以及场景有足够的了解,没有一个完整的方案是完全可以通用。
下面就结合我们使用过的八大方案以及收集的一些资料来详细聊聊,希望能让有需要的同行在工作上、成长上提供一定的帮助。
一、数据库为什么会慢?
无论是关系型数据库还是NoSQL,影响其存储系统查询性能的主要有三种:
➢查找的时间复杂度
➢数据总量
➢高负载
而决定于与查找时间复杂度的主要有两个因素:
➢查找算法
➢存储数据结构
不管哪种存储,数据量越少,查询性能自然越高,随着数据量的增多,资源的消耗就越大(如CPU、磁盘读写繁忙),耗时也会越来越高。关系型数据库基本固定是使用B+Tree来作为索引的数据结构,而索引就是用于提高数据库表的数据访问速度。对于数据检索,首先想到的是二叉树,二叉树的查找时间复杂度是O(log2(n)),二叉树搜索相当于一个二分查找,二分查找能大大提升查询效率,但是存在一个问题,有可能出现线性结构的二叉树,相当于全表扫描,查询效率极低。因此我们对于关系型数据库性能优化的一般只有数据量。
高负载造成的原因有复杂查询、高并发请求导致CPU、磁盘繁忙等,而服务器资源不足则会导致慢查询等问题。该类型问题一般会选择集群、数据冗余的方式来分担压力。
二、应该站在哪个层面思考优化?
从上图可见,自上而下总共为四层,分别是硬件、存储系统、存储结构、具体实现。层与层之间都是紧密联系,每一层的上层是该层的载体,因此越往上越能决定性能的上限,同时优化的成本也相对会比较高,性价比也随之越低。
首先以最底层的“具体实现”为例,索引的优化成本是最小的,加了索引后,不管是CPU消耗还是响应时间肯定都是立竿见影的降低。然而一个简单的SQL语句,不管如何优化索引,都是有局限的,当在这层没有任何优化空间时就得往上一层去思考,再上一层是“存储结构”,这层需思考是否从物理表设计的层面进行优化,如分库分表、压缩数据量等。如果存储结构这层的优化没有达到效果时,就再继续往上一层进行考虑,考虑关系型数据库是否不适合用在现在的业务场景中?如果是要存储,那么需要换怎样的NoSQL?所以说我们的优化思路,需要出于性价比的优先考虑具体实现,实在没有优化空间了就再往上一层考虑。当然,如果公司有钱,可以直接使用钞能力,绕过了前面三层,这也是一种便捷的应急处理方式。
该篇文章我们主要就从存储结构、存储系统