开发者学堂课程【PolarDB-X 开源人才初级认证培训课程:集群运维2:监控、SQL限流与索引优化】学习笔记(二),与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1075/detail/15544
集群运维2:监控、SQL 限流与索引优化
内容介绍:
一、 PolarDB-X 架构介绍
二、课程演示
三、如何在 PolarDB-X 中优化慢 SQL
四、 PolarDB-X SQL 限流
五、 SQL 执行的过程
六、数据库优化
七、 PolarDB-X SQL Advisor 基本原理
四、 PolarDB-X SQL 限流
首先是 PolarDB-X 的 SQL 限流,它是一个应急处理的手段。
举个例子,当 PolarDB-X 上已经正在运行了一个在线业务的时候。某一天有一个新的业务上线,但是这个业务里面的话存在一些问题 SQL :写的不那么好,会占用过多的资源,导致系统的瓶颈。这种情况下,可能常规的手段是需要联系这个业务的开发方,去跟他们去沟通,让他们去配合把这个问题 SQL 改掉;或者说临时的回滚。这样的一个过程,往往也是比较耗时的。对于已经在线的业务而言,其实是不太能够等待这一段时间的,他需要能够尽快的去做业务的恢复和止血。因此 PolarDB-X 提供了 SQL 限流这样的能力,它能够让我们快速的将问题 SQL 拦截在外,不再占用系统的任何资源,来保证已有业务的稳定运行。同时我们 SQL 限流也支持了很丰富的 SQL 匹配方法。
这边已经给出了 SQL 限流的一个语法,可以看到它支持多种的匹配方式。第一个你可以看一下支持的针对某一个 database 的某一张具体的表来做限流,他就可以做到比如只针对某一张有问题的表去限流它关于这张表的 SQL ,其他表的 SQL 不会去限到;另外也可以去按照用户名和执行的主机来去限。举个例子,假如的新业务是在某一台固定的机器上使用了一个新建的一个账号去访问的,这样便可以快速定位到这个新建的业务。当然,如果你只想对 SELECT 或者 INSERT 这样的语句去做限流,这也支持的
除此之外,还针对 SQL 的内容提供了两种匹配的方式,一种是基于关键词key word的方式,它能够根据 SQL 里面的关键字去做规则匹配,来对它进行限流;另一种的话是基于 SQL 模板的方式,可能我的业务上是基于一个模板生成了不同的 SQL ,不同的用户进来产生的是不同的参数。针对这一类的 SQL 都想把它先留住,那便可以通过模板 id 的方式去进行限流。分别给出了基于关键字和模板 id 的两个限流的语法。
五、SQL 执行的过程
既然做完了应急处理,接下来的事便是要对有问题的 SQL 进行一个分析,找出原因并对它进行优化。首先来看一条 SQL 在 PolarDB-X 上执行的过程。
它主要分成三层来看,首先是客户端会将业务 SQL 发到 PolarDB-X 的一个 CN ,会对其进行解析优化,然后生成执行计划并调度执行。对于中间可以下推的部分,会通过网络的方,直接推到每个 DN 节点上,去执行并收集返回的结果;对于不可以下推的部分,我们会等 DN 的结果返回,在CN 中进行计算,最终将结果返回到用户的客户端。在这个过程中我们主要关注的就是 CN 和 DN 两部分的资源使用和执行的耗时。针对这几种场景,我们将可能存在换 SQL 的原因分成了这三类。
1. 第一类的话是业务问题,它可能包括比如数据存在明显的数据倾斜或者不合理的分片策略。这种情况下就有可能出现某一个分片里面的数据量会非常多,然后某些分片里数据量非常少。一旦某一个SQL落到了这个数据非常多的分片,那它可能就会占用比较多的查询时间,或者产生较大的数据扫描,成为整个SQL执行的瓶颈点。这时候的话,其实可能就需要对这个表结构去进行优化和调整;还有一种是比如说业务使用上的问题,类似刚刚实验里面看到基于k这个列进行查询,但它却缺少了一个全区二级索引,导致了很多不必要的分片扫描占用了较多的 CN ,比如 CN 的CPU资源。这种情况下可能就需要进行一个 SQL 的优化,或者是创建一些索引来对这个问题进行优化;还有一种情况是这个业务或者这个 SQL 本身就是需要返回过多的数据。举个例子,比如我的业务上有一个报表查询,它本身就是需要去查询大量的数据来计算报表的结果,那这种情况下,可能就会推荐比如说一个合理的限流规则,可能不用像刚才演示的那样直接拦截,但是可以去限定它的一个并发度,避免过多的 SQL 进来占用过多的资源。
2. 第二个问题就是系统的问题。系统的问题导致的比如说业务发展过快,流量得到限速,使整个目前的资源成为瓶颈。这种情况下,可能就推荐按昨天的课程里面说的,通过谈心的扩展的方式来增加更多的机器,对问题进行一个优化;另外一种的话比如 CN 到 DN 之间的网络有抖动,导致了延迟变大。那这种情况下就需要去检查系统的网络配置是否正确,或者说网络中间的一些组件是否存在问题。
3. 第三种是执行层面的问题。因为业务上的一个 SQL 到了 PolarDB-X 的 CN 节点,会对它进行解析优化,生成相应的执行计划。在这个过程中,会根据统计信息选择合适的执行计划。如果执行统计信息过期或者不是那么准确的话,就有可能出现会选错索引或者说选错 Join 的类型或者顺序等等,这样也会导致慢 SQL 。这种情况下,我们可能就需要对 SQL 进行进一步的分析优化或者进行改写,来优化这样的问题。
六、数据库优化
这边针对刚刚提到的几种慢 SQL 产生的原因给出了相应的一些处理方式。我给出了一个列表,可以主要包括对 SQL 改写以及创建索引、对库表结构优化、调整系统配置以及增加更多的硬件。
将这几种方式通过金字塔的方式进行排布。这个金字塔自下而上的话,它的优化成本是逐步提升的,但是随之而来的是它的效果却反而是越来越差。可以看一下,像对于 SQL 级索引条约的话,对于我们而言其实并不需要花费过多的成本,却可以取得显著的效果;但是对于像硬件这样的资源,可能需要像昨天演示那样,需要加一台机器,或者说搬迁数据,是一个比较耗时,也需要付出更多成本的一种优化手段。这也是为什么当系统或者当数据库出现问题的时候,DBA 往往第一时间会先去看我们有没有慢 SQL ,然后分析这些 SQL 的执行计划,看看是否有调优或者说创建索引的可能。但是创建索引这件事,其实也是非常依赖 DBA 的经验的,也是比较耗时的。
七、 PolarDB-X SQL Advisor 基本原理
针对这种情况,刚刚也是让 PolarDB-X 提供了一个自动化的索引推荐能力叫 Expain Advisor 。下面我将对 Expain Advisor 的实现原理做一个简单介绍。它的过程可以理解大概分成三个部分:
第一个部分是可索引列的分析。就是我需要找出哪些列是可以添加索引的,这些列可能就包括 while 条件里面的列、 Join 条件里面的列,或者说group bai里面的一些列。
举个例子:可以看一下这边 Agg 这张表,它有两个列式可索引的,第一个 quantity ,它其实是我们while条件里面的一个列,比如说我while quantity<0.2。这样的话,这个列其实是可以作为我的一个索引候选项的;那还有一个partkey,其实是在 Join 里面起到了效果,它是我的一个 Join key。同时,对于 part 的表也是一样的分析方式,通过这样的第一步,找到这一条SQL里面所有可以去创建索引的列,然后去构建一个候选的索引的集合,这个候选索引的集合的构建其实是基于一个假设的:我们认为对于一张表而言,它业务产生关键影响的索引数不会超过两个,只基于这样的一个假设,我们限定了就是我们的索引的长度,也就是组合索引的长度不超过二。
在这个条件下,将所有的条件索引进行枚举,就就可以生成一个叫 Candidate Index ,也就是我们所有候选索引的一个集合。接下来我们要做的是在这些不同的索引集合里面找到那个最优的集合,并把它推荐出来,那便是我们最优的索引推荐的结果。至于是怎么找到最优的索引集合,我们是这么做的:
PolarDB-X 的优化器其实是一个基于代价的优化器,对于每一条 SQL 的话都会估算出它的执行代价。在这种情况下,优化器还提供了一个叫 What if的一个能力。什么是What if?就是告诉优化器有一个索引,但是却不是继续创建它。这种情况下请你告诉我,它的这条 SQL 的执行执行的代价是多少?那有了这样一个 What if 的能力,只需要将我刚刚构建出来的所有索引的候选集合,分别输入到我的优化器中,告诉他这个索引,如果有这条 SQL 它的一个执行代价是多少?第二个索引创建之后,它的执行代价是多少?只需要在这样的枚举中,找到执行代价最小的索引组合便是我们的最终的推荐结果。就可以达到刚刚所说的推荐出一个最优索引的一个效果。这便是 PolarDB-X 索引推荐的基本原理。