在多进程计算环境中精确跟踪内存使用的制作方法

文档序号:12141996阅读:318来源:国知局
在多进程计算环境中精确跟踪内存使用的制作方法与工艺

内存是很大程度上确定数据库性能和稳定性的关键系统资源。在本说明书中,术语“内存(memory)”,除非修改,指的是随机存取存储器。在没有足够内存存在的情况下,因为溢出或简单地出错,查询会缓慢,而导致不期望的行为。由于内存是无限的,适当内存管理是确保公平和可接受的使用以及最佳的可能用户体验的关键。

在大规模并行处理(MPP)数据库中,以下高级步骤描述了查询处理:

1.用户提交查询。

2.解析器解析查询。

3.计划器对查询进行计划并产生查询计划树,其由不同进程构成;进程可以在该树上多次发生。

4.内存配额进程向每个操作器指派限定该操作器能够使用的最大内存的一定内存配额,以限制其运行时内存分配。

5.计划被调度给多个工作者节点来以分布式方式执行。

6.每个工作者节点接收它的计划树的副本,其指示被指派给该进程的内存配额。

7.查询执行引擎执行计划。

8.通过服务器,向用户返回结果。

贯穿此过程,内存由多个查询分配。为了确保内存的公平使用和适当利用以及确保系统稳定性,系统必须进行下述操作:

1.测量每个查询的内存使用。

2.检查以了解内存使用是否在配额内。

3.对于不同查询施行(enforce)内存配额。

每个主要数据库具有内存管理器来有效率地分配和释放内存。此外,主要的数据库具有算法来在对查询的计划期间向SQL(结构查询语言)语句指派内存配额。在执行期间,内存管理器通常使用内存区域来将内存分配给SQL操作器,其主要为了效率以及为了跟踪分配。



技术实现要素:

本说明书描述了用于在计算环境中跟踪内存使用的技术。这些技术大体上涉及在计算机系统的节点中运行的多个进程中的每一个中实现内存使用跟踪器(MUT)的实例。每个MUT对于运行在与该MUT相关联的相应进程上的多个拥有者中的每一个维持内存使用的账户。每个拥有者是与公共功能相关联的代码的一个或多个区域的集合的逻辑拥有者。MUT能够确定每个拥有者的实际内存配额。MUT通过以下操作来施行每个拥有者的实际内存配额:接收每个拥有者所作出的对于内存的分配请求,相对该拥有者的实际配额来检查每个分配请求和该拥有者的账户的当前状态,批准或拒绝每个分配请求,将所述批准或拒绝传输到底层内存管理器,以及对于每个所批准的分配请求,更新该拥有者的账户。

附图说明

图1A是用于跟踪内存使用的示例系统的图。

图1B是多进程计算系统中的示例内存使用跟踪器(MUT)的图。

图2是在多进程计算系统中执行内存分配的流程图。

图3是在多进程计算系统中释放所分配的内存的流程图。

图4是在多进程计算系统中执行逻辑内存仲裁的流程图。

图5是确定账户和/或子账户的共享报头是否存在并且为账户和/或子账户分配新的共享报头的流程图。

图6是在多进程计算系统中释放内存块(memory chunk)的流程图。

图7是在多进程计算系统中执行对内存的成批释放的流程图。

图8描绘了示例数据库管理系统。

具体实施方式

1.1内存管理器系统

任何内存管理器的可用性依赖于测量每个查询的内存使用的精确度。如果测量错误或不精确,则不可能确保公平的内存使用或者确保系统稳定性。本说明书描述了内存管理器系统,其能够跟踪不同查询的精确内存使用并且提供了这些功能。内存管理器系统能够确保公平的内存使用和适当的内存利用,并且最重要的是,其能够改善系统稳定性。

因为内存管理器系统通过不同组件提供了对内存使用的精确跟踪,所以其不需要作出这三个通常的假设:

1.存在已知的内存密集型查询的集合

2.对内存密集型查询的内存使用的跟踪足够好,以确保公平使用和适当内存利用

3.内存密集型查询在独占(exclusive)内存区域的集合中分配并且存在对内存区域和内存密集型操作器的一对一映射

在示例实施方式中将在数据库管理系统(DBMS)中描述内存管理器系统。DBMS实现并行处理并且能够是MPP数据库。数据库操作于多个物理计算机节点上。在一些实施方式中,在每个节点上,一个或多个段——即段实例——被实例化。每个段是逻辑节点,并且可以被认为是虚拟机。每个段通常将运行许多进程;每个进程是个体可执行单元。每个进程具有其本身的内存配额及其本身的内存管理器系统的实例。特定进程的内存管理器系统具有一些能力来与节点上其他进程的内存管理器系统交互,稍后将对其描述。DBMS将复杂查询分成小任务且将它们分发以供执行。节点一起工作以形成单个并行查询处理系统。

内存管理器系统能够监视使用,施行配额以确保公平,以及基于系统负载来调整以确保适当的内存利用。内存管理器系统具有以下特征:

1.其跟踪不同查询的精确内存使用。

2.其提供可扩展框架以灵活地限定跟踪哪些查询;使用该框架,能够跟踪任何数目的SQL进程,以及非进程组件。

3.其能够基于分配地点(诸如代码区域的功能或文件)来测量在任意代码区域处的内存使用。这样的任意代码区域被称为内存拥有代码类型或简单被称为拥有者类型。使用代码区域的实例被称为内存拥有代码或简称为拥有者。

4.作为代码区段的内存拥有者类型均能够被指派任何数目的不同角色中的一个,例如与SQL进程相对应的表扫描、排序或汇总,或者甚至与非SQL进程组件相对应的角色,例如查询计划器。

5.内存管理器系统能够对每拥有者来从不同内存区域收集分配且能够区分单个内存区域内的对不同拥有者的分配。在跟踪分配以作为内存账户的场境(context)中,对拥有者分配和拥有者账户的引用应当总是被理解为是对拥有者的分配和账户的引用。

6.内存管理器系统能够跟踪丢失的利用。

7.内存管理器系统能够检测低系统内存并暂停或终止一个或多个查询以确保系统稳定性。

内存管理器系统基于分配地点——即作出内存分配请求的代码中的地点,来跟踪分配所有权——即哪个代码实例负责内存分配。每个分配地点与标识拥有者类型的信息相关联,在缺乏对所有权的特定指派时其可以是全方位(catch-all)的。此外,内存管理器系统框架支持多态分配地点,使得从共享库所作出的分配能够基于分配共享库进程、对库的调用的拥有者、以及进程在查询计划树的何处执行来假设多个所有权。这允许获得精确的所有权跟踪。

1.2拥有者和内存账户

内存的拥有者类型是基于代码基的逻辑划分来定义的,例如MPP DBMS的代码基。与数据库进程——例如SQL进程——相关的代码的区域或者与解析器、计划器、优化器、调度器、查询串行器和解串器、执行器或其他操作器、或者视需要的其他非进程组件相关的代码的区域,能够被识别为相异的拥有者类型。在划分被决定后,其能够以多种方式来实现,只要净效果是内存管理器系统能够对于每个内存分配确定划分的哪个实例——即哪个拥有者——应当是分配的起因。例如,利用向内存管理器系统API的调用可以将代码仪表化,所述呼叫在任何时候通知内存管理器系统哪个拥有者代码正被执行。替选地,内存管理器系统能够包括网关,通过该网关能够作出对与拥有者相对应的进程——例如数据库进程——的调用,并且网关能够提供或维持切换所有权所需的信息。然后,内存管理器系统能够在相应内存账户中记录拥有者的内存使用,所述内存账户是记录拥有者的内存使用的计数器。拥有者中的每一个能够进一步通过使用子内存账户来将其内存使用与底层子系统——诸如存储、互连、目录访问等——的内存使用分离。

拥有者具有拥有者类型。拥有者仅具有一个拥有者类型,其对应于与拥有者类型的进程或非进程组件相关联的代码的区域。每个拥有者——即该拥有者类型的实例,具有一个内存账户,其将被用于通过代码的该实例(拥有者类型)或者通过被拥有者类型的代码区域所调用的代码来记录对内存的分配,将在下面对其描述。

1.3子内存账户

子内存账户是拥有者的内存消耗的更精细的子划分。进程——例如排序(Sort)进程——可以取决于复杂子系统——诸如数据提供者、网络传输层、子计划、或者用户功能,该进程不直接负责其内存使用。内存管理器系统能够跟踪这样的子账户并且同时能够确保对所有子账户和拥有者账户的汇总仍旧在所定义的内存配额内。这在精确的每拥有者内存使用的基础上提供了内存使用的精确分离。

1.4短寿命和长寿命内存账户

内存管理器系统还提供对于账户寿命的支持,以检测执行的不同阶段。一些账户能够被标记为超出单个执行阶段而存活,其被称为长寿命内存账户,而其他能够被标记为在一个执行阶段内存活。执行阶段是抽象时间概念,其能够被用于验证内存泄漏且检查长寿命分配。对于查询执行,长寿命账户可以在整个查询或多个查询期间存活,而短寿命账户可能只在单个SQL进程中存活。

1.5内存管理器系统组件

内存管理器(MM)

内存管理器(MM)负责执行分配请求和解除分配请求。在一些实施方式中,MM是基于区域的内存管理器。每个进程可以与MM的实例相关联。对于基于区域的MM,MM以块来分配内存;一个块是单个内存分配。每个块属于特定内存区域。例如,如图1中所示,内存管理器能够管理内存的区域,示出为框的行,每个行包括多个内存的块,其由每个行中的各个框来表示。

内存使用跟踪器(MUT)

内存使用跟踪器(MUT)负责在当前拥有者的内存账户——即拥有者类型的当前实例——中记录分配。其还负责在初始分配了被解除分配的内存的拥有者账户中记录解除分配。注意:对一个拥有者的内存的解除分配能够在一个不同的拥有者活动时发生。MUT与MM交互以识别分配和解除分配活动。MUT还提供应用程序接口(API),进程代码或非进程代码能够调用该API来创建内存账户。MUT在内存账户树(memory accounting tree)中维持新创建的内存账户。其还具有API来激活和停用账户。当账户处于活动时,其拥有者是活动的分配者,这意味着只要该账户处于活动,任何新内存分配就都计入该拥有者和该拥有者的内存账户。除了提供基本账户创建、切换、和使用跟踪API,MUT还具有各种报告API以报告内存使用。

MUT能够附加地监视系统的可用内存以检查该系统是否内存低。如果系统进到临界低内存状况或者内存不足(OOM)事件,MUT能够基于预先定义的策略来暂停或终止查询。MUT还能够识别和记录消耗过度内存的查询以帮助诊断内存问题。具体的,MUT可以保存当进程的当前内存消耗的快照并向其他进程中的MUT通知该OOM事件。MUT还通过周期性检查在其他处理中是否发生任何新的OOM事件来在其他运行的进程中跟踪OOM事件。如果其检测到任何这样的进程外OOM,其还将当前进程的内存使用记入日志,使得我们得到跨系统中所有进程的内存消耗的整体局面。

MUT还使用系统内存中的共享内存以在中央监视跨节点上运行的所有查询(以及由此所有数据库进程)的内存使用。MUT能够使用共享的内存来在低内存事件或OOM事件期间确定哪个特定查询或哪些特定查询应当被终止,并且能够更新共享内存中的信息以指令一个或多个特定查询终止。

1.6内存的分配中的内存管理器系统部分的交互

内存管理器系统执行以下序列以在对内存的分配中启用适当内存监视。

1.拥有者的账户的创建:如果拥有者的代码区域开始执行,则其在合适的账户不存在的情况下将首先请求MUT创建适当内存账户。例如,如果进程——排序正在执行,则在合适的账户不存在的情况下,排序将要求MUT为排序进程创建内存账户。MUT将在内存账户树中创建内存账户,并且将其返回给排序。

类似于排序操作器,其他拥有者也能够创建它们的对应的内存账户,其能够表示拥有者的身份并保存内存使用信息。在拥有者的内存账户被创建之后,拥有者取回所有权令牌,该所有权令牌仅是指向其内存账户的指针。当需要时,拥有者能够随后使用该令牌来将其内存账户设置为活动,这指令MUT在该账户中记录内存分配。

2.内存账户切换或对内存账户的激活:一旦内存账户被创建,例如排序就将在其正执行时请求MUT将其设置为活动的拥有者。然后,MUT将排序内存账户设置为活动的内存账户。

3.请求新内存:如果必要,排序能够从MUT请求新内存。

4.分配内存:MUT与MM交互以从系统分配信息内存。

在这个过程期间,如果MUT检测到低系统内存水平,则MUT识别具有高内存消耗的查询。MUT还可以向其他进程中的对等MUT通知此低内存状况。从一个MUT到其他MUT的直接通知机制使得所有MUT能够快速行动以减缓低内存状况。MUT可以使用如先前所述的共享的内存来与其对等MUT交互。在通知后,MUT中的每一个能够通过以下方式决定暂停或终止它们各自的进程:基于预先定义的释放内存的策略,基于接收终止它们相应的进程的指令,基于访问在共享内存处指示MUT应当终止其相应进程的数据,或者通过另一方法。

5.更新内存账户:如果分配成功,则MUT在当前活动的内存账户中记录分配。如果子组件负责分配,该该分配被记录在对应的子账户中以及活动的拥有者的内存账户中。在该进程期间,MUT能够检测配额违规(violation),并且在该情况下能够拒绝分配请求。此外,MUT能够在多个拥有者之间仲裁内存以将一个拥有者的未使用的配额重新分发给另一拥有者。MUT还能够向另一进程的MUT或其他进程的MUT通话以仲裁跨进程的内存重新分发。

当系统内存以块来分配时,每个块将其自身与不超过一个内存账户相关联,如活动的内存账户在对该块的分配期间所确定的。分配的块包括报头,该报头包括支持与该块相关联的拥有者和内存账户的识别的信息,稍后将对其描述。

1.7内存的解除分配中的内存管理器系统组件的交互

内存管理器系统能够以若干方式来对内存解除分配,列举如下:

1.来自拥有者的显式解除分配请求:如果拥有者请求对内存块的解除分配,则通知MUT该解除分配。MUT从该块中的报头识别分配该块的原始拥有者,并且定位对应的内存账户。然后,MUT调整原始拥有者的账户余额(account balance)以反映解除分配,例如通过从原始拥有者的账户余额中扣除等于该块的内存量。

2.基于销亡或重置的场境的成批释放:内存管理器系统在内存区域上提供成批释放操作以释放该区域中的所有分配。MUT提供API以处置该成批释放操作。如果作出成批释放内存场境的决定,则MUT识别在该区域中分配内存的所有内存账户,并且根据它们对该区域的汇总分配来调整它们的余额。

3.销亡内存账户:MUT还支持重置或擦除内存账户树,其后仅长寿命账户会存活。具有短寿命拥有者的任何块将由滚转账户(rollover account)拥有,滚转账户是目的在于跟踪长寿命分配的长寿命账户。滚转账户的子账户承担短寿命账户中的对应子账户中的分配的所有权。结果,所有块将具有相同滚转拥有者,而不管它们的之前的拥有者如何。在跟踪合法长寿命分配外,滚转账户还能够被用于帮助诊断非预期的长寿命分配或内存泄漏。

1.8新颖特征

内存管理器系统具有以下新颖特征:

1.跟踪每拥有者的使用

内存管理器系统根据灵活定义的拥有者来定义内存分配。任何拥有者能够在多个内存区域中分配内存,并且内存管理器系统跨所有分配来自动跟踪拥有者的汇总内存足迹。因此,系统能够轻易处置内存分配,其中一个拥有者的分配横跨多个代码区域且一个代码区域能够包含归因于多个拥有者的分配。

2.灵活的所有权框架

内存管理器系统在灵活定义的拥有者类型集合上工作。拥有者类型能够是良好定义的进程、模块、子模块或甚至是一个或多个任意代码区域。代码区域能够被标注有多个不同拥有者类型,并且根据该标注,该代码区域中的任何内存分配自动被视为由该拥有者类型的拥有者来使用。这样的灵活性允许内存管理器系统测量不同进程的精确内存消耗。

3.多态所有权框架

每个代码区域能够在执行时基于逻辑角色来承担多个所有权角色。因此,公共数据结构——诸如API和共享组件,能够在运行时承担不同的所有权角色。

上面的三个新颖特征消除了对内存密集型进程的基于区域的内存使用跟踪的限制。

4.层级起源管理

SQL查询计划固有地呈树状。利用SQL计划的类树形状,内存管理器系统保持跟踪树中的所有拥有者。这允许相同拥有者类型的不同拥有者的逻辑起源分离。例如,如果在相同SQL计划中找到两个排序进程,则内存管理器系统能够通过使用计划结构树来区分它们。此外,对于非进程组件——诸如计划器、查询计划生成器、或者解析器、SQL解析器,内存管理器系统基于执行路径和调用堆栈来提供类树表示。

5.MPP数据库支持

由基于所有权模型来实现所标注代码区域而产生的灵活性允许内存管理器系统不仅支持内存密集型SQL进程——诸如散列连接(Hash Join),而且还支持非进程组件——诸如查询计划串行器和解串器以及查询计划器。即,内存管理器系统能够–

1.跟踪非进程拥有者的内存消耗:在MPP数据库平台中,非进程组件能够消耗与内存密集型进程相同或在某些情况下更多的内存。例如,关于与大量划分的关系来工作的查询计划器能够消耗大量的内存。类似地,大型计划可以调度到MPP数据库中的多个节点的运行时引入显著内存开销。

2.跟踪传统上被视为非内存密集型的进程的内存消耗:简单扫描处理,其传统上被视为是非内存密集型的,能够因为新存储类型——例如HAWQ中的复合(parquet)操作器——而变为内存密集型。

3.跟踪子系统的内存消耗:MPP数据库可以具有除标准SQL进程以外的许多进程。例如,在网络层处的查询调度期间,MPP数据库可以引入显著内存开销。内存管理器系统了解这样的分配,所以其能够确保系统稳定性和适当的内存利用。

6.内存分配的本地和全局仲裁

在MPP数据库中,工作量能够是多种且复杂的。内存管理器系统支持本地仲裁以从一个进程向另一进程重新分配内存以在进程级别针对不同工作量来调整。此外,内存管理器还支持全局仲裁机制以利用来自对等查询的空闲内存配额。

7.用于诊断内存问题的整合的支持

内存管理器系统支持不同拥有者对配额违规的检测:这允许内存管理器系统调节不同拥有者——包括SQL进程实例——的内存消耗。

内存管理器系统自动跟踪长寿命内存分配并且支持对内存泄漏的检测:内存管理器系统支持对泄漏内存的查询的识别。

在低系统内存的事件下,内存管理器系统能够识别内存拥有者和正在消耗大量内存的查询。

在紧急工作量需要的情况下,内存管理器系统支持具有大内存足迹的查询的暂停和终止。

8.支持实时数据库引擎的优化

内存管理器系统自动跟踪分配的历史并且跨多个分配来由相同拥有者共享元数据以使内存开销最小化。

通过拥有者跟踪内存使用需要拥有者的内存使用计数器的频繁更新。内存管理器系统通过合并随后的更新以最小化更新操作的数目而使开销最小化。

内存分配通常可以存活多个SQL进程。后面的SQL进程的拥有者仅仅是这样的长寿命分配的消费者,并且因此不负责它们的分配。但是,内存管理器系统虑及这样的分配以跟踪内存可用性。内存管理器系统向内存管理器系统提供长寿命分配的快速所有权切换以保持跟踪这样的分配。

2.术语

2.1公共命名

3.拥有者进程概述

3.1非进程组件操作器

3.2 MUT组件

3.3特殊内存账户

3.4设计概述

识别拥有者:

内存以层级内存区域来被分配。每个区域具有寿命,其控制被分配的内存将存活多久。内存区域的所需寿命能够取决不拥有组件和对内存的所意图使用而广泛变化。例如,取决于其是否在非常短时间——例如每元组内、或者在长持续时间——例如每聚合桶(bucket)内使用内存区域,聚合拥有者可以维持三个不同的内存区域的集合。此外,若干不同组件可以分配来自相同区域的内存。因此,内存拥有者和内存区域互相交织。这使得拥有者对内存区域进行逻辑划分成为必要,该拥有者覆盖当前内存区域并且能够横跨多个区域以正确记录每个拥有者的使用。

内存的拥有者基于内存消费者的逻辑划分来定义。与解析器、计划器、优化器、调度器、查询串行器和解串器、执行器和各个进程相关的代码段由将相应组件的源代码仪表化的编程者识别,或者通过使用实现进程向拥有者的映射的网关来识别,如本说明书中其他处所述,或者由用于指定代码到拥有者的关联的任何其他便利技术来识别。然后,这些拥有者的内存使用能够被记录在它们的对应内存账户中。拥有者的内存使用能够使用子内存账户来进一步与例如存储、互连等的底层子系统的内存使用分离。

跟踪当前拥有者:

一旦代码基的开发者确定主账户和子账户拥有者,开发者就能够利用它们相关联的所有权信息来注释不同的代码区域。内存管理器系统提供简单API,内存用户——即分配内存的组件——能够调用该API来标注它们的所有权。例如,解析器在解析查询之前能够调用适当API来告知内存管理器系统解析代码开始。在解析进程结束时,其将调用另一函数来使内存管理器系统了解解析所有权已结束。在这两个调用之间,MUT将在解析器的内存账户下记录所有内存分配和解除分配。注意,在解析期间另一拥有者有可能开始分配内存。使用层级内存账户——例如计划树下的各个拥有者以及交织的所有权二者来改变所有权,例如在嵌套循环——连接期间,两个不同子操作器可以是重复访问内存并且切换所有权。

跟踪子账户:

在子账户级别也支持内存记账。如果执行器节点依赖于存储来读取元组,或者依赖于互连来发送元组,则其能够决定独立地记账那些子系统的消费。为了正确执行,子系统内存操作需要被单独标注。这么做的一个方式是调用内存记账API来在每个子系统调用时切换到适当的子系统账户。但是,这样的切换实现以及维持很昂贵。因此,自动切换方法是优选的。

自动切换到适当子账户的解决方案是基于文件和宏的子账户标注的组合。每个文件被标注有其逻辑拥有者:例如,存储相关文件,或者互连相关文件等。每个代码区域能够在执行时基于逻辑角色来承担多个所有权角色。因此,诸如API和共享组件的公共数据结构能够在运行时承担不同所有权角色。

跟踪内存使用:

随着拥有者分配内存,MUT使用活动内存账户自动检测适当的拥有者并更新该拥有者账户或子账户的余额以反映该新分配。对于解除分配,MUT从块报头识别块的拥有者并且更新该拥有者的余额以反映解除分配。注意,分配和解除分配的所有权识别是不同的。尽管活动内存账户或其子账户中的一个承担对于所有新分配的管控,但是在解除分配期间,其被归于原始分配者,而不管当前活动的内存账户如何。在分配和解除分配记录期间,MUT还负责记录全局内存配额和全局内存使用。

跟踪违规:

包括活动内存账户的每个内存账户,将具有基于拥有者的配额的内存配额。查询的内存配额能够由开发者或管理者设置。操作器配额指派算法跨其操作器来分发查询配额。使用操作器配额信息,MUT的分配记录组件在内存管理器向MUT通知分配请求时检测任何配额违规。为了检测这样的违规,MUT将首先使用上述的过程来识别适当的拥有者及其账户。然后,MUT将通过该拥有者的总分配与该拥有者的配额进行比较来检测违规。一旦检测到违规,MUT将首先尝试通过调用与特定拥有者相关联的MUT的仲裁功能来解除分配内存以回到内存配额内。MUT能够使用其缺省仲裁功能来跨所有拥有者重新分发配额,或者各个拥有者能够提供自定义回调以实现它们的配额减少过程。如果仲裁功能能够释放足够内存以回到配额内,则MUT忽略该违规。否则,MUT将使的新分配请求无效。

显式释放操作的施行:

基于区域的内存管理器提供便利的对整个区域的成批释放(即,该区域内的所有分配被一次释放)。但是,对于一些内存区域——诸如我们频繁分配大量内存的区域,对分配的显式释放操作确保及时释放内存。MUT能够提供API来对需要对每个分配进行显式释放操作的这样的内存区域进行标记。一旦被标记,MUT就能够禁用对这样的内存区域的分配的滚转机制。然后,未显式释放的任何分配能够被归责于对其进行分配的拥有者以协助诊断每拥有者的内存泄漏。

组件设计:所有权跟踪器

具有包括分配、解除分配或使用的内存操作的代码区域能够被划分为不同的逻辑拥有者。此外,单个代码区域能够属于多个逻辑拥有者。例如,排序API能够从排序操作器、排序-合并(Merge)-连接操作器或分组(Group)-聚合操作器使用。取决于拥有的操作器,排序API所作的分配可以承担不同的所有权。

在执行期间,我们还可以具有逻辑拥有者的多个实例化。例如,排序操作器能够出现在计划树中的若干不同地方。排序操作器的这些实例中的每一个具有不同所有权,即不同实例与相同逻辑拥有者类型的不同拥有者相关联。因此,精确的所有权能够被指派给能够出现若干次但操作为单独实体的代码段。相同类型的不同拥有者能够基于它们在计划树中的位置来被区分。这能够例如通过在它们相应的操作器状态中保存内存账户指针来完成。MUT能够走查计划树以基于它们的相关计划操作器来区分不同内存账户。

在一个实施方式中,固定的子账户集合被维持在主账户下的固定大小的阵列中以供快速访问。例如,这在有用子账户的集合能够被定义用于整个DBMS时是适当的。维持子账户的任意集合的灵活的基于散列的实施方式也是可能的。

为了决定哪些代码区域构成特定拥有者,开发者可以寻求简单文件集合。例如拥有者X构成文件{Fi,Fj,Fk}。尽管基于文件集合的所有权可以为良好设计的系统工作,但是基于API的拥有者切换能够超越其来定义具有任何代码区域的逻辑拥有者。而且,如前所讨论的,多态子账户确定能够在运行时决定适当的子账户。

每个拥有者将被链接到其所有权结构(即内存账户),例如通过指针来链接。指针的使用确保所有权的快速切换而无需任何查找延迟,例如在散列表中。所有权结构的实际分配能够位于专用区域中以确保适当寿命以及清理,并且指向所有的所有权结构的指针能够使用所有权账户树来全局地走查。此外,指向每个所有权结构的指针能够被保存在对应的拥有者数据结构中。例如,排序操作器将维持指向其关联的内存账户的指针。这样,排序能够快速切换所有权而无需在内存账户树中寻找其关联的内存账户。

4.设计细节

4.1内存系统

图1A示出实现所描述的内存管理系系统的内存系统的概述。内存系统能够包括多个节点,类似于图1A中所示的节点。在一些实施方式中,每个节点包括一个或多个段,其对应于节点上的一个或多个虚拟机。内存系统能够包括主节点和多个工作者节点,其中主节点和每个工作者节点是在物理计算机主机上或物理计算机主机上的虚拟机上实现的。主节点能够指派每个工作者节点(或者简称为“节点”)对存储在内存系统中的分值据中的一部分进行操作。每个节点能够包括节点内存,并且节点内存能够由一个或多个查询利用,诸如图1A中所示的查询(i)和(j)。每个查询能够涉及一个或多个进程。如所述的,执行查询所需的进程能够基于所述的流程来确定,其中,解析器解析查询并且计划器计划该查询并产生包括与运行查询所需的进程相对应的拥有者的查询计划树。

查询中的每个进程包括MM和MUT。MM,如所述的,可以是基于区域的内存管理器或其他内存管理器,其能够处置分配请求和解除分配请求。MUT跟踪查询的进程的内存分配,其中与查询的进程相关联的每个MUT具有查询计划树的副本或者查询计划树的相关部分的副本,定义执行查询所需的进程。

查询的进程的MM中的每一个能够访问节点内存(图1A中标记为“公共内存”),以执行分配操作和解除分配操作。此外,节点内存包括不同进程的MUT通过其能够通信并且能够跟踪在该节点上运行的其他查询的内存使用的机制或渠道。在一些情况下,此通信机制或渠道能够是共享内存区域,其使得不同查询的不同进程的MUT能够通信并且评估在节点上运行的查询的内存使用状态。此共享内存区域能够是图1A中所示的条目的阵列,其中每个条目与特定查询相对应并且包括与该特定查询相关的信息。例如,共享内存中查询细节的阵列中的每个条目能够包括与查询的状态相关的信息,例如查询的开始时间、峰值内存使用、当前内存使用、查询内存配额、查询的终止优先级——例如应当执行的终止的顺序、以及执行查询的工作者进程的数目。此外,如果其被执行,则共享内存阵列中的每个条目能够包括与查询的终止状态相关的信息。例如,终止请求能够包括:指示查询是否应当终止的数据——例如标志、指示何时作出终止查询的确定的时间戳、识别终止请求进程的信息、指示作出终止请求时的节点的空余内存水平的数据、指示在发起终止之前终止进程消费了节点内存中的多少等。

在节点上运行的每个进程能够访问该通信机制——例如共享内存,并且在一些实施方式中,能够更新可经由该通信机制访问的与一个或多个查询相关联的信息。例如,各个进程的MUT能够访问共享内存上的查询细节的阵列中的一个或多个条目并且能够更新与那些条目相关联的一个或多个查询的信息。例如,查询的特定进程中的MUT能够更新与另一查询相关的阵列条目中的“应当终止”字段以指示该特定查询应当被终止。在这样的示例中,当与应当被终止的特定查询相关联的特定进程正在执行时,其能够使用其MUT来访问共享内存并确定其属于的查询应当终止。然后,该进程能够执行操作,例如,通过和与查询相关联的查询计划调度器通信,以向调度器和/或与该查询相关联的其他进程通报该查询应当终止。被指令终止的查询的终止进程可以利用确定其应当终止并且执行终止流程的其他方法。但是应当注意,确定查询应当被终止的进程和/或查询调度器,不直接终止目标查询的进程,因为这会阻止能够干净地退出进程,例如当进程处于临界部分时。

图1A中所示的内存系统形成本文所述的内存管理器系统的基础,并且其操作附加地如下所述。图8提供了对使用内存管理器系统的内存系统的其他功能的描述。

4.2分配进程

图1B示出针对进程来分配内存的流程。例如,结合查询来执行的进程能够请求新的内存分配。内存分配请求能够由执行该进程的组件提供,例如需要内存(例如进程)的特定硬件或软件组件。内存分配能够在与该进程相关联的MM处接收,如图1B中步骤1所示。

在MM接收内存分配请求时,该MM要求来自MUT的许可来分配内存。这是在图1B的步骤2所指出的。为了确定分配是否能够进行,MUT首先确定是否存在与活动拥有者——即进程的内存账户和/或子账户——相关联的映射元素,诸如共享报头或例如散列表的其他映射设备。

共享报头或其他映射元素包括与特定拥有者相关联的分配信息。因此,映射元素与特定内存账户和/或子账户相关联。在图1B中所示的实施方式中,共享报头被维持在共享报头列表中。每个共享报头列表与特定代相关联,其中每一代对应于内存系统所处理的查询。例如,图1B中的共享报头列表均与代1(“G1”)、代2(“G2”)、或代3(“G3”)相关联。每个共享报头列表包括一个或多个共享报头,例如SH1到SHn,其中每个共享报头对应于特定内存账户和/或子账户。在一些实施方式中,共享报头被维持在二维或三维阵列中,或者诸如散列表的另一结构中,其中共享报头能够根据代、活动内存区域、内存账户、和/或内存子账户来存储。

因此,为了确定活动拥有者内存账户和/或子账户的共享报头或其他映射元素是否存在,MUT确定当前活动拥有者,例如查询计划树中的活动拥有者。这是由图1B的步骤3指示的。在图1B的步骤4处,MUT还确定当前代。当前代可以被存储在查询计划树中,或者可以由MUT另外确定的。然后,MUT通过观察映射——诸如所识别的代的共享报头列表,并试图在映射中定位映射元素——例如与在该代的共享报头列表中的活动拥有者的共享报头,来确定活动拥有者的映射元素——诸如共享报头——是否存在。

如果没有定位适当映射元素,则MUT从MM中请求映射元素分配,如图1B的步骤5所示。例如,MUT能够请求MM分配新的共享报头。该分配请求由MM如任何其他分配指令一样来处理,使得该MM能够针对共享报头或其他映射元素来分配内存并且返回新的共享报头或将元素映射到MUT。MUT能够从MM接收标识新的映射元素的信息,并且MUT之后能够更新该映射元素以包括与该映射元素相关的信息,例如共享报头能够利用识别与该共享报头相关联的代、与共享报头相关联的拥有者、内存账户、和/或子账户、当前内存区域、和/或其他信息的信息来被初始化。

在图1B的步骤6处,通过在共享报头列表中定位适当的映射元素、或者通过如所述的定位新的映射元素,MUT已经定位了活动拥有者内存账户和/或子账户的映射元素。

一旦MUT具有活动拥有者内存账户和/或子账户的映射元素,则MUT能够确定是否为MM授予许可以处理在步骤1处所接收的分配请求。如果MUT批准该请求,则MUT在步骤7处发送信息到MM以向MM授予处理分配请求的许可,并且还提供用于具有关于映射元素的信息的所分配内存块的映射信息。例如,MUT能够提供向MM该信息,使得MM更新所分配的内存块报头以包括指向适当的映射元素的指针。

通过这样做,内存管理器系统能够维持在例如映射元素中的对所分配内存块的映射,其中每个映射元素与特定拥有者内存账户和/或子账户相关联。这样的映射提供对内存使用的更精确的跟踪,还通过允许更快释放内存而优化系统,因为内存能够通过识别与查询的进程相关联的适当映射元素而被释放,并且在不需要走查每个内存块的情况下释放与这些映射元素相关联的所有块。

如关于图1B的步骤7所述,MUT确定是否批准MM所提供的分配内存的许可请求。评估MM所提供的许可请求的流程在图2中更详细描述。

图2图示了评估分配请求是否应当被处理的流程。在步骤202处,与图1B的步骤2相对应,MUT从MM接收许可请求。在接收到许可请求后,MUT首先在步骤204处检查是否存在该节点的低内存状况。例如,MUT能够确定内存使用是否处于临界水平,例如80%或更高的可用节点内存,或者节点是否遇到节点内存被用尽的真OOM事件。如果MUT确定确实存在低内存状况,则MUT在步骤206处开始全局仲裁进程。该全局仲裁进程在图3中更详细描述。

在步骤208处,MUT确定与分配请求相关联的分配地点。例如,MUT能够访问指示请求内存的函数、文件、代码区域等的信息。基于确定与分配请求相关联的分配地点,MUT在步骤210处确定分配地点是否与已知逻辑拥有者相关联。即,MUT确定在步骤208处确定的特定函数、文件或代码区域是否与特定逻辑拥有者相关联。作为示例,如果分配地点被识别为与排序进程相关联,则MUT能够确定排序进程的逻辑拥有者是否已经存在。如果MUT确实识别出与分配地点相关联的逻辑拥有者,则MUT识别该逻辑拥有者,如步骤214所示。否则,如果MUT没有识别与分配地点相关联的逻辑拥有者,则MUT在步骤212使用函数映射、文件映射、或其他映射来识别与分配地点相关联的逻辑拥有者。例如,文件“file.c”或者函数“readFile”可以属于文件处置子系统,并且被指派给该逻辑拥有者。在步骤216处,MUT确定了与分配地点相关联的逻辑拥有者。

在逻辑拥有者被确定之后,MUT随后在步骤218处检查所识别的逻辑拥有者是否匹配活动拥有者的逻辑拥有者。如果所确定的逻辑拥有者匹配该活动拥有者的逻辑拥有者,则在步骤222处,与该活动拥有者相关联的内存账户被识别为分配请求将被计入其的账户。否则,MUT确定所确定的逻辑拥有者的子账户,并且在步骤220处使用该逻辑拥有者的所确定的子账户来作为分配请求将被计入的账户。因此,在步骤224处,MUT识别出分配请求将被计账的内存账户和/或子账户,例如所识别的账户将具有分配请求,如果被处理则计入其配额。

在确定内存账户和/或子账户后,MUT在步骤226处开始配额验证器,其在步骤228处确定所识别的账户和/或子账户是否在规定的配额内。如果账户和/或子账户不在配额内,或者在一些实施方式中接近超出其配额,则MUT能够在步骤230处开始本地仲裁进程。该本地仲裁进程进一步在图4中描述且能够确定与所识别的内存账户和/或子账户相关联的查询中的其他进程中的内存是否具有多余配额,使得该配额可以被重新分发给与所识别的账户和/或子账户相关联的进程。在执行本地仲裁进程之后,配额验证器能够再次被用来确定账户和/或子账户是否在配额内(例如通过返回步骤226)。

如果所识别的账户或子账户在配额内,则MUT执行在图5中描述的进程以定位与账户和/或子账户相关联的映射元素——例如共享报头,并且分配所请求的内存。这在图2的步骤232处示出。

在分配完成之后,MUT执行记账操作以记录该分配。在步骤234处,MUT在账户和/或子账户中记录分配,并且还在映射元素例如共享报头中记录分配。例如,通过将账户和/或子账户中所指示的可用内存配额减少所分配的内存量,MUT能够在账户和/或子账户中记录分配。此外,通过添加信息以识别所分配的内存块或通过调整与映射元素相关联的余额,MUT能够在账户和/或子账户的映射元素中记录分配。在步骤236处,MUT进一步确定是否更新与共享内存相关联的信息(或者以其他方式可由每个查询的进程访问的信息)以记录该分配,并且可能记录还未记录的其他先前的分配。由于访问共享内存或使用MUT的其他通信机制是昂贵的、内存密集型的进程,在一些实施方式中,可以设置分配阈值以使得MUT仅在内存的阈值量——例如1MB——被分配和/或解除分配时更新该信息。因此,共享内存不以每个分配——例如当内存一次分配1KB时——来被更新,而是可以在足够的内存分配出现时定期更新,例如总计为1MB的1KB的1000个分配和/或解除分配。如果确定要更新共享内存(或者可经由通信机制访问的其他信息),则其在步骤238处执行。

不管该信息是否被更新,图2的进程通过在步骤240处返回映射元素而结束。例如,MUT可以向MM返回与账户和/或子账户相关联的共享报头,使得分配的内存块报头能够被更新以标识该共享报头,例如指向该共享报头的指针可以被添加到所分配块的指针。

5.仲裁

图2描述了能够由内存管理器系统执行的两种类型的仲裁:全局和本地仲裁。全局仲裁被执行以在节点遇到低内存状况或OOM事件时通过终止在节点上运行的查询来释放节点内存。本地仲裁被执行以在特定进程已经或接近超过其内存配额时在查询的进程当中重新分发可用配额。如图2中所示,本地仲裁在全局仲裁之后执行,因为在进行检查特定进程有能力分配任何可用内存之前,该分配必须首先确定是否有足够节点内存可用于分配。

5.1全局仲裁

返回到执行图2中所示的流程的全局仲裁的步骤206,图3以更精细程度来图示全局仲裁进程。图3的流程开始于步骤206,其对应于图2中的全局仲裁进程的开始。MUT能够开始例如在共享内存处对查询逐个走查与运行在节点上的查询中的每一个相关联的信息以确定查询的内存使用。如图3中所示,例如,在步骤302处,MUT能够访问共享内存并开始走查与查询相对应的条目的阵列。替选地,MUT能够请求或指令所指定的对查询进行走查的进程走查查询并且返回每个查询的内存使用。无论如何,一次只有一个进程的MUT或一个指定的走查进程能够走查与查询相对应的条目。由于MUT或其他指定的走查进程遍历条目来对查询逐个地走查,在步骤304处,MUT或者指定的进程确定是否在查询信息中——例如在共享内存中——识别更多条目,即查询。如果有,则MUT在步骤306处确定或接收下一查询的内存使用。MUT或指定的走查进程通过读取查询条目——例如共享内存中的查询状态信息,来这样做。例如,图1A中所示的“当前内存”信息能够指示查询的当前内存使用。查询的内存使用等价于与该查询相关联的所有进程的总内存使用。

然后,MUT确定特定查询的查询回收因子(eviction factor)。该回收因子能够被用来对节点上运行的查询进行排序以确定在低内存状况或OOM事件的情况下回收——即终止查询——的次序。为了确定特定查询的回收因子,MUT能够在步骤310处从回收策略提供者接收回收策略。回收策略能够被用于基于在策略中阐述的参数和与可由MUT访问的查询相关联的内存使用信息来确定查询的回收因子。例如,回收因子能够基于查询的总内存使用、查询的寿命(短运行或长运行)、查询正在使用的内存配额的百分比、查询是否被识别为关键查询、或者基于任何数目的其他因素。在确定特定查询的回收因子之后,MUT能够在步骤312处保存该回收因子。例如,特定查询的回收因子能够被保存在独立的回收因子阵列中,能够在与共享内存中的特定查询相对应的条目上更新,或者能够以其他方式来被存档。然后,图3中的流程通过确定任何其他查询是否没有被评估以确定其回收因子来重复该过程。

如果所有查询已被评估,则在步骤314处,MUT确定回收的首要候选,例如应当首先被终止的查询。然后,MUT执行操作以向该查询通报其应当终止自己。在一些实施方式中,这是通过设置与待被终止的查询相对应的共享内存中的条目中的“应当终止”字段为“真”来被执行的。待被终止的查询的进程能够在稍后时间访问共享内存并且基于“应当终止”字段来确定其查询应当被终止。然后,进程能够向与查询相关联的查询计划调度器通报其进程应当被终止,并且查询能够随后通报该查询的(在一个或多个节点中)进程中的每一个以终止。然后,所有进程随着它们了解它们意图要终止而自行终止,由此释放它们的内存以用于进一步分配。

5.2本地仲裁

图4示出用于执行本地仲裁的流程,其确定在特定查询内是否存在可用内存配额,并且如果有,则重新分发所允许的可用配额。重新分发的配额可能通常是与请求内存分配的进程相同的查询中的一个或多个其他拥有者的配额。图4所图示的流程基于确定将针对内存分配计帐的账户和/或子账户在其配额之外或临界地接近超出其配额来被执行。开始于图2的步骤230,图4的流程通过初始化本地仲裁进程而开始。

在步骤402处,MUT确定与特定查询相关联的所有拥有者的总配额。在步骤404处,MUT还确定所有拥有者的总分配,即已经与进程中的拥有者中的每一个相关联来分配的内存总量。在一些实施方式中,这是基于访问拥有者内存账户和/或子账户以确定由每个拥有者分配的总内存来确定的。MUT汇总每个拥有者的内存分配以获得该拥有者的总内存分配。

然后在步骤406处,关于是否存在任何过度配额以及是否可用于重新分发来作出决定。例如,MUT能够确定所有拥有者的总内存分配是否低于所有拥有者的总内存配额。此外,在一些实施方式中,在步骤408处本地仲裁策略提供者能够向MUT提供策略,或者MUT能够以其他方式确定策略,所述策略管控过度配额可以如何被重新分发用于特定拥有者。基于该策略,关于过度配额是否能够被重新分发给超出其配额的内存账户和/或子账户作出决定。如果过度配额不存在,或者如果策略阻止过度配额被重新分发,则分配无法发生并且在步骤410处进到分配失败状况。但是,如果存在过度配额且能够被重新分发,则在步骤412处,配额能够被重新分发到将负责所请求内存分配的账户和/或子账户。在一些实例中,这是通过更新受到配额重新分发影响的一个或多个拥有者的内存账户和/或子账户来执行的,以更新它们的相应内存配额。配额可以以可以便利于应用的其他方式来被重新分发到其配额或临界接近超出其配额的账户和/或子账户。在步骤414处,在配额被重新分发之后,MUT返回图2的步骤226以检查账户和/或子账户是否在配额内,以例如进行内存分配。

5.3定位并分配共享报头

图5示出用于确定账户和/或子账户的共享报头是否存在,以及如果报头不存在则分配账户和/或子账户的新的共享报头的流程。图5的过程对应于图2的步骤232。尽管在本文中关于使用共享报头来映射内存块到特定拥有者的实施方式来进行描述,将内存映射到拥有者的其他方法可以利用相似过程来定位和/或分配内存以用于映射元素或结构。

在步骤502处,MUT已确定当前代、当前内存区域(例如当前内存区域ID)、以及当前内存账户和/或子账户。MUT能够确定该信息,例如在图1B中所图示的步骤3和步骤4。使用此信息,MUT能够在步骤504处确定代、内存区域、账户、和/或子账户的当前组合的共享报头(或者其他映射)是否存在。例如,MUT能够通过访问共享报头的散列表、访问特定共享报头列表、在共享报头的二维或三维阵列中查找特定共享报头等,来试图识别与当前代、内存区域、账户、和/或子账户相对应的共享报头。例如,图1B示出存储在共享报头列表中的共享报头,其由代来区分。

如果识别出与所识别的代、内存区域、账户、和/或子账户相对应的共享报头,则在步骤516处返回该共享报头,并且分配进程能够进行。例如,内存块能够由MM来分配,并且内存块报头被更新以包括指向所返回的共享报头的指针,而共享报头能够被更新以识别所分配的内存块。

如果没有识别出与所识别的代、内存区域、账户、和/或子账户相对应的共享报头,则流程前进到步骤506,其中创建了新的共享报头。例如,新的共享报头能够在共享报头散列表、列表、或阵列中的适当位置被创建。其他映射元素能够被创建以记录被所分配内存向拥有者的映射。在步骤508处,用于共享报头的内存能够由MM来分配。例如,MUT能够请求MM分配用于新创建的共享报头的当前活动内存区域中的内存,例如在图1B的步骤5中。一旦新创建的共享报头以及被分配,跟踪所有共享报头和/或块报头的汇总内存使用的分配开销账户就能够被更新以反映针对新的共享报头所分配的内存(步骤510)。MUT还能够在步骤512处初始化新创建的共享报头以包括与该共享报头和/或其相关账户和/或子账户相关的信息。例如,共享报头能够被初始化以包括标识当前代、当前内存区域、和与共享报头相关联的账户和/或子账户的信息。如上所述,在共享报头随后被返回时,在步骤514处,初始化的共享报头被保存以用于账户和/或子账户的稍后的重用。尽管这里关于共享报头进行了描述,但是其他映射元素可以被类似地初始化、在分配开销账户中被存档、以及被保存以供重用。

6.释放内存

6.1释放单个分配

图6描述了释放与内存账户和/或子账户相关联的内存块内存,以及与释放的内存账户和/或子账户相关联的共享报头的过程。图6的流程开始于确定当前代以及确定其关联的内存被释放的共享报头的代。当前代可以使用例如类似于图1B的步骤4处所述的过程的过程来确定。映射元素——例如共享报头——的代能够通过访问该映射元素中的信息来被确定。例如,共享报头的代能够使用在图5的步骤512处所述的初始化进程期间被添加到共享报头中的信息来确定。一旦当前代和映射元素的代已经被确定,在步骤606处MUT确定映射元素的代是否先于当前代,例如共享报头的代是否较老。如果映射元素的代较老,则MUT将长寿命滚转账户视为待释放的内存块的拥有者,如步骤608处所示。但是,如果当前代和映射元素的代匹配,则MUT将与映射元素相关联的拥有者视为块的拥有者,例如,与共享报头相关联的账户和/或子账户。这在图6的步骤610处示出。基于在步骤606-610处作出的决定和后续决定,在步骤612处MUT确定基于内存释放而待调整的适当内存账户和/或子账户。

然后,在步骤614和616处,MUT将所确定的内存账户和/或子账户的余额以及映射元素的余额调整所释放的内存量。在步骤618处,MUT确定映射元素的余额——例如共享报头的余额——是否已经减少到零,即与映射元素的账户和/或子账户相关联的所有内存是否已经被释放。如果该余额已经被减少到零,则不再存在被分配用于映射元素的关联的账户和/或子账户的任何内存,并且在步骤620处,MUT能够因此指令MM释放映射元素内存。基于该映射元素——例如共享报头——被释放,开销账户余额能够在步骤622处被更新以将开销账户余额减少等于所释放的映射元素的内存使用的量。

不管映射元素是否被释放,在步骤624处,确定是否更新例如共享内存的节点上的进程可访问的信息以反映所释放的内存,例如以更新共享内存来指示等于自上一次共享内存更新以来的所释放内存量的内存量现在可用。如所述的,该确定能够基于阈值分配或解除分配阈值量以阻止对该信息的不必要的访问和更新,所述信息是访问和/或更新的昂贵资源。如果更新节点上所有进程可访问的信息的条件被满足,则在步骤626处共享内存被更新以反映自上次更新起的分配和/或解除分配——包括与内存释放相关联的内存解除分配。然后,在628处MUT能够返回指示释放进程已成功完成的信息。

6.2成批释放

图7描述了执行在单个流程中释放内存的特定区域上的所有内存的成批释放操作的过程。在整个内存区域的释放操作期间,MUT必须调整待被释放的每一块的对应的拥有者的余额。MUT通过披露成批释放API来优化该调整,所述成批释放API能够走查与内存区域相关联的共享报头的列表以快速调整在该内存区域中分配内存的所有拥有者的余额。这确保了许多拥有者的余额调整快速发生,而无需走查区域中每个内存块。

图7的流程开始于在步骤702处初始化成批释放进程并且开始走查在正被释放的内存区域中的映射元素——例如共享报头中的每一个,而不管映射元素的代如何。例如,内存区域的共享报头能够具有多个相关联的代,并且MUT或专用走查进程能够走查这些共享报头中的每一个。此流程在图7的步骤704和706处示出。在步骤708处,MUT正在分析的——即在走查中的——当前映射元素的代与当前代进行比较。这类似于图6中关于步骤606所描述的过程。类似于MUT释放流程,如果被评估的映射元素的代比当前代更老,则在步骤710处,滚转账户被视为是与内存释放相关联的拥有者内存账户。如果正在被评估的映射元素的代匹配当前代,则在步骤712处,与该映射元素相关联的账户和/或子账户被确定。因此,在步骤714处,MUT已经识别了内存释放将与其相关联的账户和/或子账户。

在识别账户和/或子账户后,MUT随后将该账户和/或子账户的余额调整该映射元素所指示的全余额。例如,账户和/或子账户的余额能够被调整适当共享的报头所指示的余额。由于特定内存区域上的所有块都被释放,并且由于映射元素——例如共享报头特定于特定内存区域、代、以及账户和/或子账户,因此映射元素的全余额能够从在步骤714处识别的账户和/或子账户的内存余额扣减。此扣减发生在图7的步骤716处。其后,由于映射元素的余额已经被有效减少到0,因此在步骤718处MUT能够请求MM释放共享报头。除了请求映射元素的内存被释放以外,MUT还能够在步骤720处减少分配开销账户余额以反映映射元素的内存的释放。如所述的,分配开销账户余额能够被减少等于映射元素——例如共享报头的内存使用的量。类似于图6的步骤624和626处所述的过程,然后MUT能够在步骤722处确定是否更新由节点上的所有进程可访问的信息,例如共享内存,以反映映射元素的释放和/或先前与所释放的映射元素相关联的所释放的内存块。如果是,则在步骤724处,MUT更新信息,例如共享内存。

然后,步骤726确定在未被释放的特定内存区域中是否存在剩余映射元素——例如其他共享报头,并且如果存在,则返回步骤706以重复图7的流程的相关部分。无论代以及账户和/或子账户如何,如果内存区域的所有映射元素,已经被释放,则区域的所有内存块也被释放,并且过程能够在步骤728处通过返回成批释放流程成功的指示而结束。

7.内存系统

图8是示例系统810的图。系统810图示了数据库管理系统810,在其上能够实现本说明书中描述的创新技术。

在系统810中,数据是跨多个存储设备的分布式数据。节点814a到814n能够通过与能够是例如Hadoop文件系统(HDFS)的底层存储系统通信来访问数据,所述节点在有必要将与主节点进行区分时能够被称作工作者节点。数据能够被复制——即数据的完全相同的副本能够被存储在多个存储设备上,或者被划分——即数据的不同部分能够被存储在多个存储设备上。例如,数据部分能够是大规模并行处理(MPP)数据库的表划分。

系统810包括主节点812和多个工作者节点814a、814b、至814n。主节点812和每个工作者节点814a-n被实现为物理计算机主机或物理计算机主机上的虚拟机。主节点812指派每个工作者节点以对存储在第一系统810中的数据的部分进行操作。

例如,如所图示的,系统810包括被指派为对第一数据库表的第一分区816a进行操作的第一工作者节点814a。类似地,第二工作者节点814b被指派对第一数据库表格的第二分区816b进行操作。系统810能够包括任意数目N的工作者节点,一直到工作者节点814n——其被指派来对第一数据库表的第N分区进行操作。

多个用户设备能够访问系统810。用户设备802的用户能够通过与主节点812通信来访问系统810中存储的数据。主节点812与工作者节点814a-814n协调以响应来自用户设备802的对于数据的请求。用户设备802能够向主节点812发布查询,例如以结构化查询语言(SQL)中或对象查询语言(OQL)的查询。主节点812与工作者节点814a-814n通信以获得满足该查询的数据。主节点812能够维持提供数据部分与被指派来对该数据部分进行操作的工作者节点之间的映射的系统目录。系统810能够访问其他外部系统上存储的数据。

当主节点812接收查询时,主节点812解析该查询并生成查询计划。查询计划定义主机节点812将向工作者节点分发以履行查询的操作。主节点812能够访问系统目录并执行成本估计和优化算法以确定减少成本的查询计划,例如履行查询的所需处理时间和网络带宽。主节点812的功能可以由执行不同功能——例如查询解析器812a和查询计划器812b的多个软件模块来实现。

除了所附权利要求书的实施例和上述的实施例,以下的所编号的实施例也是创新的:

实施例1是一种装置,包括:

计算机系统,包括一个或多个操作地互连的主机,每个主机包括计算机和一个或多个存储设备,所述存储设备存储指令,所述指令可操作以在所述一个或多个主机上被执行时,使得所述一个或多个主机在计算机系统的节点中运行的多个进程中的每一个中实现内存使用跟踪器(MUT)的实例,所述内存使用跟踪器的每个实例可操作以对该实例在其上运行的进程执行以下操作:

对于运行在该进程上的多个拥有者中的每一个维持内存使用的账户,每个拥有者是逻辑拥有者的实例,每个逻辑拥有者是与公共功能相关联的代码的一个或多个区域的集合;

确定每个拥有者的实际内存配额;以及

对于每个拥有者来施行该拥有者的实际内存配额,包括:

接收每个拥有者所作出的对于内存的每个分配请求;

相对该拥有者的实际配额来检查每个分配请求和该拥有者的账户的当前状态;

批准或拒绝每个分配请求,并且将所述批准或拒绝传输到底层内存管理器;以及

对于每个所批准的分配请求,更新该拥有者的账户。

实施例2是实施例1所述的介质,其中,对于每个拥有者施行该拥有者的实际内存配额进一步包括:

接收一个或多个解除分配请求以对先前由拥有者分配的内存解除分配,并且对于每个解除分配请求:

识别先前分配该内存的拥有者;以及

更新该拥有者的账户。

实施例3是实施例2所述的介质,其中,所述操作进一步包括:

从内存使用跟踪器所维持的、从所分配的内存单元映射到进行分配的拥有者的映射中识别先前分配该内存的拥有者。

实施例4是实施例1-3中任一项所述的介质,其中,所述操作进一步包括:

对于一个或多个多态拥有者中的每一个维持内存使用的子账户,每个多态拥有者是多态逻辑拥有者的实例,每个多态逻辑拥有者是与公共功能相关联的代码的一个或多个区域的集合,每个多态拥有者针对相应的拥有者来运行;以及

将针对拥有者运行的多态拥有者所作的任何分配请求计入该拥有者的账户以及该多态拥有者的子账户。

实施例5是实施例1-4中任一项所述的介质,其中

所述一个或多个计算机存储介质是非暂时性的;

所述多个逻辑拥有者包括作为代码的多个非毗连区域的集合的逻辑拥有者;

初始地确定每个拥有者的实际内存配额作为该逻辑拥有者的逻辑内存配额;以及

所述底层内存管理器是基于区域的内存管理器。

实施例6是实施例1-5中任一项所述的介质,所述操作进一步包括:

接收表示每个逻辑拥有者的逻辑内存配额的数据;以及

根据对应的逻辑拥有者的逻辑内存配额,确定每个拥有者的实际内存配额。

实施例7是实施例6中任一项所述的介质,所述操作进一步包括:

在具有长寿命分配的账户和任何子账户的原始拥有者已经终止之后,将所有权从所述原始拥有者切换至滚转账户。

实施例8是实施例1-6中任一项所述的介质,所述操作进一步包括:

当包括多个逻辑拥有者的程序的寿命的新分区开始时,根据划分该寿命的逻辑执行模型来将所有权从账户和任何子账户的原始拥有者切换至滚转账户。

实施例9是实施例1-5中任一项所述的介质,所述操作进一步包括:

接收表示查询计划树的数据,所述查询计划树是SQL查询的SQL查询计划的一部分,所述查询计划树包括表示SQL操作器的操作器节点元素和表示非SQL操作器的非操作器节点元素;以及

根据与所述查询计划树相对应的账户树结构来维持每个拥有者的内存使用的账户,其中,每个拥有者具有逻辑拥有者,该逻辑拥有者具有执行所述查询计划树的对应操作器节点元素的操作的代码。

实施例10是实施例9所述的介质,其中,所述操作进一步包括:

接收表示所述查询计划树中的每个操作器节点元素的初始内存配额的数据;以及

根据所述查询计划树中的对应的操作器节点元素的初始内存配额,确定每个拥有者的实际内存配额。

实施例11是实施例10所述的介质,其中,所述操作进一步包括:

接收针对相同的SQL操作器具有带有不同初始内存配额的多个操作器节点元素的查询计划树。

实施例12是实施例9-11中任一项所述的介质,所述操作进一步包括:

在所述查询计划树的操作已经终止之后,将所有权从具有长寿命分配的账户和任何子账户的原始拥有者切换到滚转账户。

实施例13是实施例9-11中任一项所述的介质,所述操作进一步包括:

当SQL查询终止时,将所有权从账户和任何子账户的原始拥有者切换到滚转账户。

实施例14是实施例1-8中任一项所述的介质,所述操作进一步包括:

从在所述计算机系统的与所述内存使用跟踪器的所述实例相同的节点中运行的一个或多个其他内存使用跟踪器实例获得内存使用数据;

检测影响在所述计算机系统的与所述内存使用跟踪器的所述实例相同的节点中运行的全部的所述多个进程的低内存状况;以及

从由在所述相同的节点中运行的全部的内存使用跟踪器实例跟踪的拥有者当中识别特定拥有者作为应当被终止的拥有者。

实施例15是实施例14所述的介质,所述操作进一步包括:

当所述特定拥有者运行在与所述内存使用跟踪器的所述实例相同的进程中时,终止所述特定拥有者。

实施例16是实施例1-8中任一项所述的介质,所述操作进一步包括:

从在所述计算机系统的与所述内存使用跟踪器的所述实例相同的节点中运行的一个或多个其他内存使用跟踪器实例中获得每任务内存使用数据;

检测影响在所述计算机系统的与所述内存使用跟踪器的所述实例相同的节点中运行的全部的所述多个进程的低内存状况;

确定所述多个进程中执行的多个更高级别任务中的每一个的汇总内存使用和汇总配额,其中,所述更高级别任务中的每一个包括一个或多个拥有者;

基于所述任务中的每一个的所述汇总内存使用和所述汇总配额之间的关系来确定该任务的分值;

选择具有最差分值的特定任务作为待终止的任务;以及

当所述特定任务在与所述内存使用跟踪器的所述实例相同的进程中运行时,终止所述特定任务。

实施例17是实施例16所述的介质,其中:

获得内存使用数据包括获得每任务内存使用数据,

实施例18是实施例9-17中任何一项的介质,所述操作进一步包括:

从在所述计算机系统的与所述内存使用跟踪器的所述实例相同的节点中运行的一个或多个其他内存使用跟踪器实例中获得每查询内存使用数据;

检测影响在所述计算机系统的与所述内存使用跟踪器的所述实例相同的节点中运行的全部的所述多个进程的低内存状况;

确定在所述多个进程中执行的多个SQL查询中的每一个的汇总内存使用和汇总配额,其中,所述SQL查询中的每一个包括一个或多个拥有者;以及

从由在所述相同的节点中运行的全部的内存使用跟踪器实例跟踪的查询当中识别特定SQL查询作为应当被终止的特定SQL查询。

实施例19是实施例18所述的介质,所述操作进一步包括:

确定所述特定SQL查询的一部分正运行在所述多个进程中所包括的特定进程上,以及终止正运行在所述特定进程上的所述特定SQL查询的所述一部分。

实施例20是实施例19所述的介质,所述操作进一步包括:

通知运行所述特定SQL查询的部分的全部的其他进程以终止它们相应的所述特定SQL查询的部分。

实施例21是实施例1-20中任一项所述的介质,所述操作进一步包括:

通过响应于拥有者超出其实际内存配额而调整运行在进程上的拥有者的实际内存配额,来在拥有者当中进行仲裁。

实施例22是一个或多个计算机存储介质,编码有计算机程序指令,所述计算机程序指令在被一个或多个计算机执行时,使得所述一个或多个计算机在计算机系统的节点中运行的多个进程中的每一个中实现内存使用跟踪器(MUT)的实例,所述内存使用跟踪器的每个实例可操作以对该示例在其上运行的进程执行实施例1-21中任一项所述的操作。

实施例23是一种方法,其包括执行在实施例1-21中任何一项所述的操作。

当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1