书接上文GaussDB高智能--自治运维技术(中),从日志分析、慢SQL发现、慢SQL诊断、集群故障根因诊断等方面介绍了GaussDB的自治运维技术,本篇将从索引推荐、分布键推荐、参数调优等三方面继续解读GaussDB的自治运维技术。
数据库的索引管理是一项非常普遍且重要的事情,任何数据库的性能优化都需要考虑索引的选择。GaussDB支持原生的索引推荐功能,通过系统函数及运行工具等形式进行单条索引推荐及负载级别索引推荐。智能索引推荐功能可覆盖多种任务级别和使用场景,主要包含三个能力。
(1) 单条查询语句的索引推荐。该特性可基于查询语句的语义信息和数据库的统计信息,对用户输入的单条查询语句生成推荐的索引。
(2) 虚拟索引。该特性可模拟真实索引的建立,同时避免真实索引创建所需的时间和空间开销,用户可通过优化器评估虚拟索引对指定查询语句的代价影响。
(3) 基于工作负载的索引推荐。该特性将包含有多条DML语句的工作负载作为任务的输入,最终生成一批可优化整体工作负载执行时间的索引。该功能适用于多种使用场景,例如,当面对一批全新的业务SQL且当前系统中无索引,本功能将针对该工作负载量身定制,推荐出效果最优的一批索引;当系统中已存在索引时,本功能仍可查漏补缺,对当前生产环境中运行的作业,通过获取日志来推荐可提升工作负载执行效率的索引,或者针对极个别的慢SQL进行单条查询语句的索引推荐。
1. 单Query索引推荐
单条索引推荐以数据库的系统函数形式提供的,用户可以通过调用gs_index_advise()命令使用。其原理是利用在SQL引擎、优化器等处获取到的信息,使用启发式算法进行推荐。该功能可以用来对因索引配置不当而导致的慢SQL进行优化。其执行流程图如下:
在单条索引推荐的过程中,主要包括以下步骤:
(1)对给定的查询语句进行词法和语法解析,得到解析树;
(2)依次对解析树中的单个或多个SelectStmt结构进行分析;
(3)整理查询条件,分析各个子句中的谓词:
解析from子句,提取其中的表信息,如果其中含有join子句,则解析并保存join关系;
解析where子句,如果是谓词表达式,则通过在数据库中执行包含谓词表达式的select语句来计算各谓词的选择度,并将各谓词根据选择度的大小进行倒序排列,选择度越大,位置越靠前(左)。当某一列有多个谓词条件时,会根据条件中最大的选择度决定该谓词的排序位置,依据最左匹配原则添加候选索引。目前暂不支持join on对选择度的影响。如果是join关系,则解析并保存join关系;
如果是多表查询,则将结果集最小的表作为驱动表,根据前述过程中保存的join关系为其他被驱动表添加候选索引;
解析group和order子句,判断其中的谓词是否有效,如果有效则插入到候选索引的合适位置,注意到仅当group或order子句的所有谓词来自同一张表并且是驱动表时进行处理,group子句优于 order子句,两者只能同时存在一个;这里采用启发式规则,对候选索引按优先级排列为:join中的谓词 > where 等值表达式中的谓词 > group或order中的谓词 > where非等值表达式中的谓词。
过滤重复索引,根据最左匹配原则,合并索引,并检查该索引是否在数据库中已存在;
输出最终的索引推荐建议。
单query索引推荐的详细设计如下:
(1)对FROM子句的解析和处理
从from子句中提取出RangeVar结构,保存相关的表的信息;
如果from子句含有join子句,则对join子句进行解析和处理,提取和保存相关的表信息和关系表达式。
(2)对WHERE子句的解析和处理
提取出where子句中的谓词表达式,如果是or连接符,则忽略相关表达式,只处理and连接符相关的表达式;
依次对提取出的谓词表达式进行解析和处理,当表达式中的操作符为like时,如果不是前缀匹配则丢弃;计算谓词的选择度,并根据选择度大小进行倒序排序,其中如果选择度小于设定的阈值丢弃该谓词;
谓词选择度的计算方法:取得表的总行数table_count,则数据的采样范围为rand_rows =(table_count / 2) > 1W ? 1W : (table_count / 2),执行查询语句,求得在采样范围内满足该谓词表达式的结果的行数rows,最终选择度cardinality = rand_rows / rows。
将谓词添加到候选索引中,排序的规则为,等值表达式的谓词优先于不等值表达式的谓词,当谓词同属于等值或不等值表达式时,则按照选择度大小进行排列,选择度大的谓词排在前面。
区分where子句中的join条件,进行相应地解析和处理
(3)对JOIN子句的解析和处理
Join语法分为两种:join on 和 join using,需要分情况进行处理,其中join on 有时会存在where子句中;
Join关系以二叉树的形式进行存储,以后序遍历的方式对二叉树进行遍历,解析join中的谓词表达式,为涉及的连接表保存相关的谓词和关系表达式;
经过前期的where解析、join解析,已经将SQL中表关联关系存储起来,并确定了侯选驱动表,在侯选驱动表中,按照每一张表的侯选索引字段中第一个字段进行计算表中结果集大小,选择结果集最小的表作为驱动表;
根据保存的join关系为被驱动表添加候选索引。
(4)对GROUP/ORDER子句的解析和处理
将group 子句与order 子句中的谓词添加为候选索引,需要满足如下条件:涉及到的谓词必须来自于同一张表;是单表查询或者谓词来自于驱动表;Group子句中的谓词优先于order子句中的谓词,且两者只能同时存在一个;Order子句中谓词的排序方向必须完全一致,否则丢弃整个Order子句;
如果子句中的谓词有效,则插入到对应表的候选索引中,插入位置应在where等值表达式和非等值表达式的谓词之间。
2. Workload级别索引推荐
Workload索引推荐是针对给定的负载,给出一批符合该负载状况下的最优索引组合。推荐后的索引,不一定对所有执行语句都有正向收益,但对整批负载的收益是正向的。在Workload级别索引推荐中,主要包括两个核心功能,一是虚拟索引的设计,二是workload级别索引推荐算法设计。Workload索引推荐执行流程图如下:
在针对负载进行索引推荐的过程中,主要包括以下步骤:
(1)首先对进行工作负载的压缩。工作负载中通常情况下存在大量相似重复的SQL语句。因此首先对SQL语句进行模板化,将谓词表达式中具体的参数值用统一的占位符替代,同时采用水库抽样的方法采样和保留部分参数的真实值;
(2)对给定的工作负载,逐条进行单条索引的推荐和生成;
(3)对单条语句的推荐索引,进行索引验证,根据推荐建议生成虚拟索引;再查询优化器针对该语句的执行计划,检验该推荐索引是否被数据库采用,如果有效,则加入候选索引集合;
(4)对候选索引集合中的每个索引,计算该索引对整个负载的收益,以及对创建索引的开销进行估计;
(5)利用虚拟索引功能估计索引真实创建所需的空间大小,采用优化算法求解基于用户限定的索引集合中索引数目的大小或限定的索引集合的空间大小下,最大化索引集合的总收益,得到最终的推荐索引集合。
(6)输出最终的索引推荐建议。
其中虚拟索引的详细设计如下:
(1)在数据库内部建立虚拟索引,该虚拟索引只具有真实索引的结构体中的信息,包括创建索引的表名、列名和其他数据库需要的统计信息,避免了真实索引的创建开销,该索引仅适合于优化器进行估计,不能提供真正的索引扫描;
(2)对单条语句执行EXPLAIN,查看优化器的执行计划,检验该推荐索引是否被数据库采用以及是否减少了执行代价。
workload级别索引推荐的详细设计如下:
(1)对每条query, 执行单条索引推荐,生成单条query的候选索引;
(2)基于步骤一的候选索引中的候选列,依次从单列逐渐递增到多列,迭代地生成多列索引。在每次迭代过程中,采用虚拟索引+优化器估计的方式对该多列索引进行验证和评估;重复步骤一和步骤二,生成的多列(单列)索引共同组成候选索引集合;
(3)基于候选索引集合,选择出多个原子的索引集合。原子索引集合的定义为,如果存在一个query,可以用到该集合的所有索引,则该集合是原子的。
(4)采用虚拟索引+优化器估计的方式获取并记录所有原子集合对工作负载的代价;
(5)初始化一个空的索引集合,然后迭代地从候选索引集合中逐渐增加索引,在每次迭代过程中,只添加使得该集合的总代价最小的索引。这里,索引集合对工作负载的总代价,为索引集合对工作负载中每个SQL语句的代价之和。任意索引集合对指定SQL语句的代价计算,都可根据原子索引集合对该SQL语句的代价计算得到;
(6)生成最终推荐的索引集合。
分布键推荐功能主要针对Hash分布策略进行推荐,为每个表推荐合适的分布建,使得整体工作负载的运行效率达到最优。 分布键推荐功能的执行流程图如下:
分布键推荐功能根据时间节点划分,可划分为两种使用场景,一是在数据迁移前,可支持两种数据格式,一种是基于友商数据库中的存储过程和少量关于数据分布的统计信息,另一种是基于友商数据库的统计报告和少量关于数据分布的统计信息进行初步的分布键推荐;该场景可以在迁移工具进行集成,在迁移过程中,调用该工具完成业务迁移。二是在完成数据迁移并运行一段时间业务后,基于真实的工作负载和优化器的代价估计,进一步改进和完善分布键的推荐结果。
在初始阶段,为防止数据倾斜的问题,先将根据表的统计信息,首先将可能造成分布严重倾斜的列从分布键的候选集合中排除出去。具体而言,计算表中每列上不同值的个数和表的总行数的比值,只有当该比值大于设定的阈值时,该列将加入分布键推荐的候选集合。
(1)场景一:数据迁移前
将友商数据库中全部的workload(如存储过程、SQL语句)导出到文件中;
使用sqlparse模块(Python第三方库,一种SQL语法解析包)对存储过程语句进行词法和语法解析;
提取出所有的join条件,采用基于粗略代价估计的图算法针对join关系进行分布键的推荐;
提取出所有的group子句,统计高频的列,并加入分布键的候选推荐;
选择主键的第一列,加入分布键的候选推荐;
步骤3到5,作为分布键的候选列的优先级依次降低,对每个表,返回优先级最高的列作为最终的推荐结果。
(2)场景二:运行业务后
采用场景一推荐的分布键或者默认的分布键设置,完成从Oracle到GaussDB的数据迁移;
获取工作负载。提供2种方式获取:一是从日志中自动解析和抽取;或者从数据库的WDR功能提供的视图中获取;
连接数据库获取SQL语句的执行计划;
使用sqlparse对SQL语句进行词法和语法解析;
提取出所有的join条件,采用基于优化器代价估计的图算法针对join关系进行分布键的推荐;
提取出所有的group子句,基于优化器的执行计划,计算和统计其中高代价的列,并加入分布键的候选推荐;
提取出所有的谓词表达式predicate,当该predicate的结果集大小大于设定的阈值时,考虑将数据打散到各个节点,因此predicate中的列不考虑加入分布键的候选推荐;反之,当该predicate的结果集大小小于设定的阈值时,将predicate中的列加入分布键的候选推荐;
选择主键的第一列,加入分布键的候选推荐;
步骤5到8,作为分布键的候选列的优先级依次降低,对每个表,返回优先级最高的列作为最终的推荐结果。
分布键推荐功能的详细设计如下:
分布键推荐功能的核心算法是基于粗略/优化器代价估计的图算法,主要包括下面内容:(1)根据提取的join关系建图,图中的顶点代表数据库中的表,图中的边代表两个表之间的连接关系,每个边包含两个属性,每个边的权重为join关系的代价。例如,当提取的join关系为
(t1、t2和t3为表,c1、c2和c3为对应关系中的列名),则join关系的图如下图所示:
(2)根据代价计算方式的不同,可分为基于粗略代价估计的图算法和基于优化器代价估计的图算法。粗略的代价估计方式:如果存在两个表t1和t2,其大小分别为b1和b2,
为节点的总数量,则对两表join的代价
可采用下式进行估计,即为当join关系采用重分布或广播时产生的代价中的最小值:
基于优化器的代价估计方式:在一些SQL中,在执行join前可能会对其中的表进行过滤和筛选,并不是全表进行关联,因此使用优化器对join关系的估计代价更为精确。
(3)采用贪心策略的图算法:
建完图后,分布键的推荐问题转化为在该图上求解优化问题:在join关系图中,每个顶点最多选择一个属性作为分布键,在满足限制条件下,尽可能多地选择边,使得选中的所有边的权重和最大。为了求解上述优化问题,采用基于贪心策略的图算法进行求解。
算法一:首先初始化两个空的候选集合和,在每次迭代过程中,随机选择图中一个度至少为1的顶点,然后对于所有与u相连的边,选择出权重最大的边,并将此边的另一个顶点加入候选集合,以及去除所有不再合法的边。对候选集合重复以上过程。依次在候选集合和中增加顶点,最终选取两者中权重和最大的集合作为最终的推荐结果。
算法二:将图中所有的边按照权重从高到低进行排序,然后从最高权重的边依次进行处理,如果当前边是合法的,则加入结果集。每次向结果集中加入一个顶点后,一部分以该顶点为端点并且连接属性不一致的边将会失效,视为不合法的状态。返回结果集作为推荐结果。
GaussDB提供超过500多个可配置参数,根据业务应用不同及服务器硬件配置不同,需要调整不同的参数来满足客户的需求。由于可配置操作众多,运维人员很难在较短时间内确定好合适的参数及其配置,通过AI技术可以较好解决该问题,帮助客户在上线前快速完成参数调优。
参数调优的流程图如下:
在整个调参过程中,参数调优服务是一个离线型组件,是整个调优系统的核心组件。在该组件中,分为两个功能。当模型处于训练阶段中,根据输入的数据库参数数值通过强化学习和启发式算法得到新的参数数值组合,模型将新的数值植入数据库并运行测试作业得到当前数值组合下数据库的性能表现,最后将表现作为反馈给学习模型,往复迭代;当模型处于测试阶段中,将当前数据库的参数数值作为输入,通过模型得到当前情况下的所能得到的最优参数调整方案。
(1)启动调参流程的前提条件是用户已导入数据,准备好自己的典型业务SQL作为调参输入。
(2)训练阶段:
输入:组件外部将数据库参数数值作为输入参数,其中包括数据库当前参数数值以及数据库当前性能参数数值。
模型:组件由两部分模型组成,强化学习和启发式算法。数据库的参数调整建议由两个组成部分的输出结果混合得到。
反馈:将模型的输出经过反归一化得到新的参数数值,将新的数值植入数据库并运行测试作业得到当前数值组合下数据库的性能表现,如执行时长、吞吐量等指标。最后将表现作为反馈给学习模型,往复迭代。
(3)测试阶段。
输入:将当前数据库的参数数值作为输入,其中包括数据库当前参数数值以及数据库当前性能参数数值。
输出:得到基于当前状况下的适用于与测试作业相同作业的最有参数数值组合。
参数调优的系统详细设计:
(1)在Tuner中通过强化学习和启发式算法对数据库的参数进行优化。客户端通过SSH链接到服务器端,并通过shell命令对数据库参数进行更新。
(2)在强化学习中,根据马尔可夫决策过程,使用四元组对决策过程进行描述:
State:表示当前的状态,在Tuner中具体体现为数据库的当前关键参数数值和相对应的性能指标参数数值。为提高泛化性,各数值需要进行归一化处理,保证数值的取值范围[0,1]。
Action:表示采取的动作,在Tuner中体现为各个参数的相对变化,取值范围[-1,1].
P:表示采取的动作策略,已采用概率的形式存在。
Reward:表示动作奖励,在Tuner中体现为将数据库参数设置为新数值后,执行特定作业所耗费的时间等参数。
(3)通过学习转移方程,优化参数取值。
(4)在强化学习之外,模型还采用了粒子群优化算法用于组合参数的优化。通过群体智能算法对NP问题求取最优解。
(5)最终将两个算法得到的参数结果进行处理混合,得到最后的参数数值。
以上内容从索引推荐、分布键推荐、参数调优等三方面继续解读GaussDB的自治运维技术,下篇我们将对GaussDB的库内AI引擎进行详解解读,敬请期待~