标题:连接顺序枚举的深度强化学习
***摘要***:连接顺序选择在查询性能中起着重要的作用。但是,现代查询优化器通常使用静态连接顺序枚举算法,这些算法不包含关于结果计划质量的反馈。因此,优化器经常重复选择相同的坏计划,因为它们没有“从错误中学习”的机制。在这里,我们认为深度强化学习技术可以应用于解决这一挑战。这些由人工神经网络驱动的技术可以通过结合反馈自动改进优化器的决策。为了实现这一目标,我们提出了ReJOIN,一个概念验证的连接枚举器,以及初步结果,表明ReJOIN在计划质量和连接枚举效率方面可以匹配或优于PostgreSQL优化器。
介绍
确定关系查询的良好连接顺序是数据库系统(例如[6,12,13,18])中研究得最多的问题之一,因为选择的连接顺序对查询性能有重大影响[11]。连接顺序选择的一个主要挑战是枚举一组候选顺序并确定最经济有效的顺序。搜索更大的候选空间增加了找到低成本排序的几率,但代价是花费更多时间进行查询优化。因此,连接顺序枚举器同时寻求最小化所枚举计划的数量和所选计划的最终成本。
传统的DBMS采用各种连接枚举策略。例如,System R[18]使用动态规划来寻找成本最低的左深连接树,而PostgreSQL[1]则贪婪地选择低成本的关系对,直到树被建立。许多商业产品(例如,[3])允许DBA通过结构约束(例如,仅限左深计划)或在经过一段时间后切断枚举来控制候选计划空间的大小。不幸的是,这些启发式方法常常会错过好的执行计划。更重要的是,传统的查询优化器依赖于静态策略,因此不能从过去的经验中学习。传统系统计划查询,执行查询计划,然后忘记曾经优化过这个查询。由于缺乏反馈,查询优化器可能会重复选择相同的错误计划,而不会从之前的正确或错误选择中学习。
在本文中,我们分享了我们对基于学习的优化器的愿景,该优化器利用先前的经验,旨在学习如何更有效地(即更好的查询计划)和高效地(即更少的优化时间)优化未来的查询。我们介绍了一种新的基于深度强化学习(DRL)的查询优化方法[5],这是一个机器在神经网络的帮助下通过持续反馈学习任务的过程。我们认为现有的深度强化学习技术可以利用更少的优化时间来提供更好的查询计划。
作为第一步,我们提出了ReJOIN,一个完全由深度强化学习驱动的概念验证连接顺序枚举器。在第2节中,我们描述ReJOIN。在第3节中,我们提供了有希望的初步结果,表明ReJOIN在有效性和效率方面可以优于PostgreSQL的连接枚举过程。据我们所知,这项工作是第一个使用深度强化学习做出查询优化决策的工作。并发工作[14]正在研究用于学习查询优化过程中每个步骤的表示的深度学习方法。以前的自适应方法[4,7,19]使用查询执行反馈来修复不正确的统计估计。
THE REJOIN ENUMERATOR
接下来,我们提出我们的概念验证深度强化学习连接顺序枚举器,我们称之为ReJOIN。
-
Join Enumeration
ReJOIN采用许多现代DBMS(例如[1,10])使用的传统的基于成本的查询优化方法。具体来说,给定一个SQL查询作为输入,连接顺序枚举器搜索所有可能连接顺序的子空间,并选择“最便宜”的顺序(根据成本模型)执行。该枚举不执行索引选择、连接算子选择等——这些任务留给DBMS优化器的其他组件。连接顺序由二叉树捕获,其中每个叶节点表示一个基本关系。图1显示了关系A、B、C和D的三种可能的连接顺序。
-
Reinforcement Learning
强化学习假设[5]agent与environment相互作用。environment告诉agent它的当前状态和一组潜在动作
= {
} agent可以执行。agent选择一个action a∈
,environment根据这个action给agent一个reward
。环境还为agent提供了一个新的状态
和一个新的动作集
。这个过程不断重复,直到agent到达一个terminal状态,此时没有更多的动作可用。这标志着一回合的结束,之后新的回合开始。agent的目标是通过学习自己的经验(之前的动作、状态和奖励)来最大化自己的奖励。这是通过平衡对新策略的探索和对现有知识的利用来实现的。
-
Overview
我们将连接顺序枚举过程表述为一个强化学习问题。发送到优化器的每个查询代表一个回合,ReJOIN在发送查询时不断学习。除了有关查询连接和选择谓词的信息外,每个状态将表示二叉连接树的子树。每个动作表示将两个子树组合成一个树。子树既可以表示输入关系,也可以表示子树之间的连接。当所有输入关系都连接起来时,回合结束(终止状态)。此时,ReJOIN根据优化器的成本模型为最终的连接排序分配奖励。最终的连接排序被发送给优化器,生成的物理计划由DBMS执行。
ReJOIN的框架如图2所示。形式上,给定一个查询q访问关系,我们定义q的回合的初始状态为
= {
}。这个状态表示为状态向量。该状态向量通过神经网络反馈[16],产生潜在动作的概率分布。任何状态的动作集
是从1到
的每一个唯一有序整数对,包括:
=
×
。动作(x,y)∈
表示将
的第xth个和第yth个元素连接在一起。神经网络的输出用于选择一个动作(即,一个新的连接),该动作被发送回环境,并转换到一个新的状态。选择动作(x,y)后的状态
为
=
。新的状态被输入到神经网络中。每个非终止状态(部分排序)的奖励为零,而到达终止状态
(完全排序)的动作的奖励是连接树t代价
的倒数,由
,
表示。agent定期利用其经验来调整神经网络的权重,旨在获得更大的奖励。
-
Example
图3显示了涉及四个关系的查询的潜在集:A、B、C和D。初始状态为 = {A, B,C,D}。动作集
为每个有序关系对包含一个元素,例如(1,4)∈
表示A与D的连接,(2,3)∈
表示B与C的连接。agent选择动作(1,3),表示加入A和C的选择。下一个状态
= {A⋈C,B,D}。agent接下来选择动作(2,3),表示选择加入B和D。下一个状态是
= {A⋈C, B⋈D}。此时,agent只有两种可能的选择,
= {(1,2),(2,1)}。假设agent选择了动作(1,2),则下一个状态
= {(A⋈C)⋈(B⋈D)}表示最终状态。此时,agent将根据成本模型对最终连接排序的评估获得奖励。
2.1 State Vectors
ReJOIN需要每个状态的向量表示,它捕获有关连接树结构和连接/选择谓词的信息。接下来,我们概述了一个简单的向量化策略,它捕获了这些信息,并证明了即使在有限的输入数据下,强化学习策略也是有效的。
-
Tree Structure
为了获取树结构数据,我们将每个二叉子树(即迄今为止确定的连接顺序)x∈ 编码为大小为n的行向量v,其中n为数据库中关系的总数。如果第i个关系不在x中,则值
为零,否则等于
,其中h(i,x)是关系
在子树x中的高度(到根的距离)。在图3的例子中,倒数第二个状态{A⋈C, B⋈D}的树向量的第一行对应于(A⋈C),第一行第三列的值为
,对应子树中高度为2的C。第一行的第二列的值为0,因为关系B不包括在子树中。
-
Join Predicates
为了捕获关于连接谓词的关键信息,我们为每个回合创建一个n × n的二进制对称矩阵m。如果存在连接第i和第j个关系的连接谓词,则值为1,否则为0。这个简单的表示捕获了可行的等于连接操作。图3显示了这样一个矩阵m的例子。由于谓词A.id = B.id,所以值
=
= 1。值
=
= 0,因为没有连接B和C的连接谓词。
-
Selection Predicates
选择谓词向量是一个k维向量,其中k是数据库中属性的总数(所有关系中的属性总数)。当第i属性在给定查询中具有选择谓词时,第i值为1,否则为零。这揭示了哪些属性用于/不用于过滤元组。例如,在图3中,B.a2对应的值是1,因为谓词B.a2 > 100。
2.2 Reinforcement Learning
-
Policy gradient
ReJOIN依赖于策略梯度方法[22],这是强化学习的一个特定子集。策略梯度强化学习agent根据参数化策略选择动作,其中θ是表示策略参数的向量。给定状态
和动作集
,策略
为
中的每个动作输出一个分数(在我们的上下文中,是组合两个连接子树的分数)。然后使用各种方法选择动作[5]。
强化学习的目的是优化回合上的策略,即识别优化期望奖励
的策略参数θ。然而,奖励
通常无法精确计算,因此策略梯度方法通过构造奖励梯度的估计量E来搜索最优策略参数:E(θ) ≈
。
给定一个估计E,梯度上升方法通过在梯度为正值时将
中的每个参数增加一个小值来调整初始参数θ(正梯度表明
的较大值将增加奖励),并在梯度为负值时将
中的参数减少一个小值来调整初始参数θ。
-
Policy gradient deep learning
策略梯度深度学习方法(如[17])将策略表示为神经网络,其中θ为网络权值,从而实现
的高效微分[16]。图2显示了我们在ReJOIN中使用的策略网络。将当前状态的向量化表示输入状态层,在状态层中对每个值进行转换并发送到第一个隐藏层。第一个隐藏层将其数据转换并传递给第二个隐藏层,第二个隐藏层将数据传递给最后一个动作层。动作层的每个神经元代表一个潜在的动作,它们的输出归一化形成一个概率分布。策略
(
)从这个概率分布中抽样选择动作,平衡了探索和利用[22]。
策略梯度是使用前一回合(查询)的样本估计的。每次完成一个回合(选择给定查询的连接顺序)时,ReJOIN agent记录一个新的观察值(θ,r)。这里,θ表示该回合使用的策略参数和最终获得的成本(奖励)r。给定在多个回合上的一组经历 X = {
,
,…,
},各种先进的技术可以用来估计期望奖励的梯度E(θ)[17,21]。
初步结果
在这里,我们提供了初步的实验,表明ReJOIN可以在成本和延迟方面与PostgreSQL[1]优化器生成的连接排序一样好(甚至更好)。
我们的实验利用了Join Order Benchmark (JOB),这是一组在之前的查询优化器评估中使用的查询[11]。基准测试包括IMDB数据集上33个查询模板的113个查询实例。我们已经创建了一个预加载了数据集的虚拟机[2]。每个查询连接4到17个关系。两个最大的关系包含36M和15M行。ReJOIN在103个查询上进行了训练,在10个查询上进行了测试。我们的测试查询集包括一个随机选择的查询模板(模板#1)的所有实例,以及其他六个随机选择的查询。
使用PostgreSQL[1],在2核、4GB RAM和最大共享缓冲池大小为1GB的虚拟机上,数据库总大小为11GB(所有主键和外键都被索引)。我们将PostgreSQL配置为执行ReJOIN生成的连接排序,而不是使用自己的连接枚举器。
ReJOIN使用了近端策略优化(PPO)算法[17],这是一种现成的[15]最先进的DRL技术。我们使用两个隐藏层,每个隐藏层有128个改正线性单元(relu)[8]。
-
Learning Convergence
为了评估ReJOIN的学习收敛性,我们反复运行ReJOIN算法,在每回合开始时从训练集中随机选择一个查询。结果如图4所示。x轴表示ReJOIN agent迄今为止学习的查询(回合)的数量,y轴表示生成的计划相对于PostgreSQL优化器生成的计划的成本,例如,200%的值表示一个计划的成本是PostgreSQL优化器选择的计划的两倍。ReJOIN开始时没有任何信息,因此最初的性能非常差。随着观察到的回合(查询)数量的增加,算法的性能也会提高。在大约8000个观察到的查询中,ReJOIN开始寻找比PostgreSQL优化器预测成本更低的计划。在10,000次查询之后,ReJOIN生成的计划的平均成本是PostgreSQL生成的计划成本的80%。这表明,经过足够的训练,ReJOIN可以学会生成有效的连接排序。
-
Join Enumeration Effectiveness
为了评估ReJOIN产生的连接排序的有效性,我们首先用从103个训练查询中随机选择的10,000个查询来训练我们的系统(这个过程花费了大约3个小时)。然后,我们使用生成的模型为我们的10个测试查询生成连接排序。对于每个测试查询,我们使用聚合模型来生成连接排序,但是我们没有更新模型(即,模型没有将任何关于测试查询的信息添加到它的经验集中)。我们记录了由这些测试连接排序产生的计划的成本(根据PostgreSQL成本模型)以及它们的执行时间。我们比较了ReJOIN与PostgreSQL以及Quickpick[20]的有效性,Quickpick对100个半随机连接排序进行启发式采样,并选择连接排序,当给出DBMS成本模型时,会产生最低成本计划。
Optimizer costs
我们首先根据成本模型的评估评估ReJOIN枚举器产生的连接顺序。由PostgreSQL的默认枚举进程、Quickpick和ReJOIN在10个测试查询上生成的计划的成本如图5a所示。x轴上的“Query XY”指的是模板X的实例Y。平均而言,ReJOIN产生的连接排序导致查询计划比PostgreSQL优化器便宜20%。在最坏的情况下,ReJOIN产生的成本只比PostgreSQL优化器(15a)高2%。这表明ReJOIN能够学习一种通用策略,该策略的性能优于或匹配由PostgreSQL优化器生成的连接排序的成本。Quickpick相对较差的性能表明ReJOIN的良好性能不是由于随机的机会。
Query latency
图5b显示了Quickpick和ReJOIN创建的查询计划的执行延迟相对于PostgreSQL创建的计划的性能(10次执行,冷缓存)。最小、最大和中位数的延迟改进被展示。ReJOIN的连接排序产生的计划优于或等于PostgreSQL产生的计划。因此,ReJOIN可以产生执行时间更短的计划(不仅仅是优化器成本更低)。Quickpick相对较差的性能表明ReJOIN不是简单地猜测随机连接顺序。
-
Join Enumeration Efficiency
关于神经网络和机器学习的一个普遍观点是,它们需要的操作过于昂贵,无法包含在数据库内部。这里,我们将演示ReJOIN之类的方法实际上可以减少查询规划时间。图5c显示了所有113个查询的平均总查询优化时间,按要连接的关系数量分组。我们包括ReJOIN在策略更新和不更新时的计划时间。
Planning latency
对于PostgreSQL,正如预期的那样,查询中更多的关系会导致更高的优化时间,因为需要考虑更多的连接排序并在成本模型中运行。然而,ReJOIN可以将其模型以时间线性的方式应用于关系的数量:在每一轮中,两个子树被连接,直到产生完整的连接顺序。因此,虽然PostgreSQL的查询优化时间增加得比线性还慢,但ReJOIN的查询优化时间(相对)是平坦的。
Policy update overhead
使用PPO执行每回合策略更新的额外开销相对较小,例如 <12ms。但是,一旦ReJOIN模型充分融合,就可以跳过策略更新,从而将查询规划时间额外减少10%到30%,从而实现更短的查询规划时间。
开放的挑战和持续的工作
我们对连接枚举的简单强化学习方法表明,在将深度强化学习算法应用于查询优化问题方面还有很大的发展空间。总的来说,我们相信ReJOIN开辟了令人兴奋的新研究路径,下面我们将重点介绍其中一些。
-
Latency optimization
成本模型依赖于基数估计,这通常容易出错。使用执行计划的实际延迟(而不是成本模型的估计)作为奖励信号是可取的。ReJOIN使用成本模型作为查询性能的代理,因为它使我们能够快速训练大量回合的算法——执行查询计划,特别是在早期集中生成的糟糕计划,将会非常耗时。我们目前正在研究技术[9],通过首先观察一个专家系统(例如,Postgres查询优化器),模仿它,然后改进模仿策略来“引导”学习过程。
-
End-to-end optimization
ReJOIN只处理连接顺序选择,并且需要优化器来选择算子、选择索引、合并谓词等。可以开始扩展ReJOIN,通过修改操作空间以包含操作员级别的决策来处理这些问题。