动态和自动内存管理的制作方法

文档序号:6428556阅读:241来源:国知局
专利名称:动态和自动内存管理的制作方法
背景技术
在典型数据库系统中,用户通过把命令提交给诸如Oracle之类的数据库应用,来存储、更新和检索信息。当进行事务处理时,数据库应用把信息存储在内存中和盘上。为了使性能最佳,除了盘之外,还必须把尽可能多的信息存储在内存中。但是,由于内存资源是有限的,数据库应用必须协调涉及到把可用内存分配给数据库应用使用的结构的内存分配。
正如可从Oracle公司和因特网上网址htt//oradoc.photo.net/ora81/DOC/server.815/a67781/toc.htm获得的图书《Oracle8i概念》(将该图书的全文插在本文中,以供参考)所述的那样,数据库应用Oracle所使用的两种结构是称为系统全局区(SGA)和程序全局区(PGA)的内存区。SGA包含有关Oracle进程需要访问的数据库和实例的状态的一般信息。在SGA中不存储用户数据。SGA的尺寸在启动Oracle的时候确定。为了使大多数系统的性能最佳,整个SGA应该与实内存相适应。数据库管理器(DBA)通过发出SQL语句“SHOW SGA”。可以看到多少内存被分配给SGA和它的每个内部结构。
PGA是当进程开始时,为保存数据和控制每个进程的信息而创建的。PGA专用于Oracle中的每个进程,但这样的PGA可以处在共享内存中。PGA初始尺寸在启动相应进程的时候是固定的,并且是操作系统专用的。当前,在Oracle8i中,DBA可以利用像SORT_AREA_SIZE、HASH_AREA_SIZE、BITMAP_MERGE_AREA_SIZE和CREATE_BITMAP_AREA_SIZE那样的各种参数,控制PGA内存利用。有关这样参数的更多信息,请参阅可从网址htt//oradoc.photo.net/ora81/DOC/server.815/a67775/toc.htm获得的图书《Oracle8i Tuning》(将该图书的全文插在本文中,以供参考)。
还可以参阅名称为“按照指定值或阈值为存储来自排序操作的数据分配专用或共享缓冲内存的方法(Method for allocating either private or sharedbuffer memory for storing data from sort operations in accordance with anassigned value or threshold value)”、授予Cohen等人的美国专利第5,799,210号、名称为“串行可重用执行内存(Serially reusable execution memory)”、授予Jasuja等人的美国专利第5,987,144号、名称为“允许大量进程访问巨型物理内存缓冲区的寻址方法和系统(Addressmg method and system for providingaccess of a very large size physical memory buffer to a number of processes)”、授予Frank等人的美国专利第5,860,144号,以及名称为“利用位图索引在计算机中进行动态内存分配(Dynamic memory allocation in a computer using a bitmap index)”、授予McMahon等人的美国专利第5,784,699号,所有这些专利都与数据库进程使用内存有关。
有关附加信息,请参阅Luc Bouganim、Olga Kapitskaia和Patrick Valduriez发表在Networking and Information Systems 1(6)629-652(1998)上的论文《大型查询执行的动态内存分配》(“Dynamic Memory Allocation for Large QueryExecution”)。还可以参阅这三位作者发表在pages 105-115 of Proceedings ofConference on Information and Knowledge Manage- ment,1998 published byAssociation for Computing Machinery,Inc上的论文《大型查询执行的内存自适应调度》(“Memory-Adaptive Scheduling for Large Query Execution”)。这个领域中的另一篇论文是Diane L.Davison和Goetz Graefe发表在SIGMODConferene 1995281-292上的论文《多用户查询执行的动态资源中介代理》(“Dynamic Resource Brokering for Multi-User Query Execution”)。
发明概述按照本发明编程的计算机对定义供诸如数据库之类的应用使用的总内存量的值敏感。在一个例子中,数据库管理器(DBA)提供这样的值(也称为“外部设置全局值”)。在另一个例子中,外部设置全局值是根据例如系统中当前可用的内存量自动确定的。此后,计算机按照(全部或至少部分)从外部设置全局值中导出的量值分配内存(例如,供数据库查询用)。
编程计算机的一个实施例从外部设置全局值中导出用在为应用分配内存(例如,实现数据库查询的操作符所需的内存中的内部值(称为“内存限度”)。内存限度可以以对于本领域普通技术人员来说显而易见的任何方式例如取决于实现数据库的进程和结构导出。
在一个实施例中,编程计算机根据完成的内存分配,动态地修改内存限度,从而形成反馈回路。可选地,在确定内存限度时,编程计算机可以对应用之外的信息(诸如非数据库进程分配的内存量敏感),以便有效地使用计算机中的有限内存。
附图简述

图1A以数据流图的形式例示了按照本发明编程的计算机中的数据和逻辑块;图1B例示了如图1A所示那种类型的计算机中的一种应用执行的步骤;图2以高级方块图的形式例示了如图1B所示那种类型的多服务器进程对共享内存的使用;图3以流程图的形式例示了在图1B的服务器进程执行的比较步骤的一个详细描述当计算机被基于本发明的软件编程时,它对定义供诸如数据库之类的应用使用的总内存量的值11(图11A)敏感。请注意,尽管在如下的描述中涉及数据库应用,但是,取决于实施例,也可以以本文所述的方式编程其它应用。值11(也称为“外部设置全局值”)可以由例如数据库管理器(DBA)提供,或者可以根据例如计算机中当前可用的内存自动确定。取决于实施例,外部设置全局值11可以被应用用作极限值(不能超过它),或者被用作目标值(有时可以达到,或者大多数时间不可以达到例如未达到或已超过)。
在一个实施例中,数据库系统10(图1A)通过对不适用于例如进行查询的应用进程的内存量12(图1A)加以考虑,计算数据库软件内部的值14(下文称为“全局内部值”)。具体地说,逻辑块13(图1A)对已分配但未使用的内存(称为“空闲内存”)和与实现查询的操作符(诸如排序、散列连接和位图合并)无关的内存(称为“其它内存”)加以考虑。
取决于实施例,数据库系统10(图1A)利用全局内部值14来计算(参见逻辑块15)用在为每个操作符分配内存中的另一个内部值17(也称为“内存限度”)。内存限度17是用于每个操作符工作区的、定义可以每个进程18分配的内存量的操作符级值。每个进程18将内存限度17与操作符所需的内存量20相比较,以确定要分配的内存量,然后,分配适当的内存量。但是,取决于数据库的类型(例如,分层)和/或实现数据库的结构和进程,可以直接从外部设置全局值中,即,无需计算如上所述的全局内部值14就可以导出内存限度。此外,在可替代实施例中,不使用操作符级值14,而是每个进程在对有关实现反馈回路的内存使用的统计表加以考虑的同时,根据全局内部值14,或甚至根据外部设置全局值11(取决于实现)确定要分配给操作符的内存量。
在一个这样的实施例中,数据库系统10(图1A)按如下实现反馈回路如果数据库系统10当前分配的总内存超过外部设置全局值,那么,数据库系统降低内存限度(反之亦然),以便使数据库系统10分配的总内存接近作为如上所述的目标值或极限值的外部设置全局值11。如果不使用内存限度,那么,即使值11保持不变,这样的实施例也可以改变全局内部值14。
上述操作可以以就公开文件而言,对于本领域普通技术人员来说显而易见的任何方式实现。例如,反馈回路可以以周期性地或异步地,或周期性地和异步地修改内存限度17(和/或全局内部值14)为基础。在一个实施例中,数据库系统10根据与内存使用有关的统计表,周期性地(例如,每3秒钟一次)修改内存限度17。当分配内存时例如如果数据库系统10分配的总内存超过外部设置全局值11达预定值(可以是例如零或值11的10%),数据库系统17也可以异步地修改内存限度17。此外,如果认为操作符的优先级比其它操作符的优先级高,分配的内存量21可以是所需的量20,或者可以是内存限度17或从这些量之一或两者中导出的某个量例如内存限度的倍数,或估计值的倍数。在刚刚描述过的例子中,代替优先级,可以把某个量的“货币”分配给每个操作符,而内存限度17可以是利用货币“购买”内存支付的价格。在这样的情况下,分配给每个操作符的“货币”量决定操作符接受的内存量。
在一个实施例中,数据库系统10包括计算上述内存限度17的指令序列(下文称之为“内存中介器”)。内存中介器22可以当作与实现数据库查询的进程分立和不同的进程来实现。在这种情况下,数据库查询进程18将内存限度17与一个或多个估计值相比较,并且分配适当的内存量。信息在内存中介器22和数据库查询进程18之间的传送可以通过消息,或通过共享内存实现。
在一个可选实施例中,内存中介器的指令序列不是被建立成分立进程,而是每个数据库查询进程利用函数调用来调用这些指令。因此,公共函数可以用于为所有操作符分配内存(不是将不同函数用于如下所述的“排序”和“散列”操作符)。当使用这样的公共函数时,每个进程直接使用外部设置全局值(如上所述)来导出要分配的内存量。
在内存中介器只计算全局内部值14(如上所述),和每个查询进程使用全局内部值14来导出要分配给操作符的内存量的另一个实施例中,组合了某些实施例的特征。此外,取决于实施例,当为每个操作符分配内存时,可以不同地使用内存限度17例如较高优先级的查询可以分配多达2倍或3倍于内存限度的内存,而一般优先级查询分配多达内存限度的内存。因此,在本例中,操作符的极限值取决于打算执行操作符的特定查询的优先级。在另一个例子中,取代“极限值”,内存限度起“价格”的作用。此外,不是将一个公共内存限度17用于所有操作符(例如,用于正常优先级查询),而是使用几个内存限度,每种类型的操作符使用一个内存限度。
在一个实施例中,当分配内存时,操作符所需的工作区内存通过每个进程来估计,和取决于操作符将操作的模式例如(1)没有盘访问的最佳模式;(2)存在盘访问,但要求对盘上的所有数据只进行一遍扫描的一遍扫描模式;和(3)要求对盘上的数据进行多遍扫描的最小模式,在一种实现中,作出几种估计。操作符执行查询所需的时间取决于执行的模式例如如图6所示,在最佳模式下所需的时间最短,在最小模式下所需的时间最长,和一遍扫描所需的时间在最长和最短之间。请注意,对于同一操作符,取决于输入数据的尺寸,这样的估计可以随查询不同而不同。此后,在这种实现中,取决于这些估计和取决于内存限度,每个进程为操作符分配内存量。
例如,调用“排序”操作符的进程按如下确定要分配的工作区(也称为“排序区”)内存量如果最佳内存估计值小于内存限度,采用最佳内存估计值;如果内存限度在最佳内存估计值和一遍扫描内存估计值之间,采用一遍扫描内存估计值;并且如果内存限度小于一遍扫描内存估计值,采用最小内存估计值。
在这个特殊的例子中,调用“散列连接”操作符的进程按如下确定要分配的工作区(也称为“散列区”)内存量如果最佳内存估计值小于内存限度,采用最佳内存估计值;如果内存限度在最佳内存估计值和最小存估计值之间,采用内存限度;并且如果内存限度小于最小内存估计值,采用最小内存估计值。这是因为散列连接操作符可从一遍扫描估计值和最佳估计值之间的额外内存中获得好处,而排序操作符则不能从中获得好处。在本例中,如果内存限度小于最小内存估计值,那么,在一个实施例中,所有操作符接受它们各自的最小内存估计值,而在另一个实施例中,这样的操作符排队等候(直到内存限度增加到超过最小内存估计值为止)。
因此,数据库系统10使DBA能够协调当使用现有技术数据库时难以人工协调的内存参数。具体地说,分配的内存量的调整应该取决于操作符的相对使用频率、每个操作符的内存要求和系统中同时激活的操作符的设置。这些条件可以在一天内改变许多次,尤其在特殊环境下。请求者所熟知的现有技术参数不会自动调整,因此,它们不能补偿系统中过低或过高的内存使用。此外,请求者所熟知的现有技术参数不控制查询将使用的最大内存量,这势必加重内存的过度分配,并且往往因内存耗尽而引起系统崩溃。最后,这样的现有技术参数往往浪费PGA内存,因为分配的内存多于需要的内存,以获得可接受的性能。当使用如上所述的外部设置全局值11时,这种在现有技术中未得到使用的内存被其它查询或甚至被其它应用较好地利用。
实现上述操作的一个实施例的计算机100(图1B)执行许多软件程序,如操作系统101、商务逻辑块102、联网应用103和数据库应用110。计算机100可以是像IMB个人计算机(PC)那样的任何计算机,或像Ultra Sparc II那样的Sun工作站。计算机100包括执行指令的一个或多个中央处理单元(CPU)、保存数据和指令的非易失性存储器(譬如盘)和在执行期间临时保存数据和指令的易失性存储器(譬如DRAM(动态随机访问存储器))。计算机100还包括互连CPU和存储器的总线。计算机100可以包括向用户显示信息的显示设备(譬如阴极射线管)和从用户接收命令的一个或多个输入设备(譬如键盘和/或鼠标)。
在如下的描述中,不言自明地要求使用这样的计算机100,即使没有明确地说出这样的使用。数据库应用110执行各种类型的查询,把信息存储在数据库中和从数据库中检索数据(数据库可以是例如关系数据库)。每次查询可以在正常模式下,通过诸如排序、散列连接和位图合并之类的一个或多个操作符来执行。在执行每次查询期间,计算机100按如下所述分配内存。分配直接或间接地基于外部设置全局值11(通过数据库参数PGA_AGGREGATE_TARGET的值来表示)。在这个特定实施例中,值11用作为供执行数据库查询的进程(有时称为“服务器进程”)内部使用而分配的总内存的目标值。在一个实施例中,用户界面111(图1B)从数据库管理器接收(参见步骤112)全局值11,将该值存储(参见步骤113)存储在共享内存中。每个进程(至少部分地)根据从共享内存中读取的值11,分配供它内部使用的内存。
数据库110的一个实施例包括从全局值11中和可选地从有关当前内存使用的统计表中导出(参见图1B中的步骤116)内部值,和存储该内部值,供服务器进程在分配内存时使用。取决于实现,内部值可以是应用于通过所有进程120A-120Z分配的内存的全局内部值14,或只应用于为操作符分配的内存的操作符级内存限度17。根据内存使用统计表,内存中介器115通过服务器进程120A-120Z(其中,A≤I≤Z,Z是当前进程数),对内存分配作出响应,动态修改内部值,从而形成反馈回路(如图1B中的支路118所示)。
取决于实施例,服务器进程120A(参见步骤121)利用外部设置全局值11或内部值14和17之一来确定要分配的内存,然后分配内存。接着,进程120A更新(参见步骤122)有关内存使用的统计表(例如,指出已分配的内存量),并且转向以正常方式执行查询。根据查询处理的完成,进程120A(参见步骤123)解除分配以前分配的内存,并且还更新(参见步骤124)内存使用统计表。
如上所述,取决于实施例,内存中介器115在步骤116中利用内存使用统计表来修改内部值14和17之一或两者。例如,内存中介器115可能发现存在太多的进程和总分配内存可能显著超过外部设置全局值11,在这种情况下,内存中介器115降低内部值14和17之一或两者,以便将来通过进程分配较少的内存量(比当前内存量少)。另一方面,如果内存中介器115发现存在太少的进程和总分配内存明显未达到外部设置全局值11,那么,内存中介器115可能提高内部值14和17之一或两者,以便将来通过进程分配较多的内存量。在这个实施例中,外部设置全局值11和内部值14和17被试图使目标值与某个范围交会的数据库应用110当作目标值来对待。
这个实施例的内存中介器115周期性地运行(例如,每3秒钟一次),修改进程120A-120Z用来分配内存的内部目标值。但是,服务器进程120I也可以调用内存中介器115例如如果总分配内存超过外部设置全局值11达预定量的话。具体地说,在一个实施例中,进程120A计算(参见图1A中的步骤125)所有进程120A-120Z分配的总内存和外部设置全局值11之间的差值(下文称之为“偏移值”)。在一种特定实现中,“偏移值”是指示从内存限度17的最后计算中得出的内存的增加分配量或解除分配量的带符号数。每当重新计算内存限度17时,这种特定实现就把偏移值设置成0。此后,为操作符分配内存的每个进程120I将偏移值增加所分配内存的数量(类似地,当释放内存时,将偏移值减少释放内存的数量)。
在分配之后,进程120A检验偏移值是否超过例如外部设置全局值11的10%,如果是的话,调用内存中介器115。当得到调用时,内存中介器115以如上所述的方式修改内部值14和17之一或两者。当解除分配内存时,进程120A也可以计算偏移值(参见图1B中的步骤126)和警告内存中介器115。
取决于实施例,内存中介器115可以使用全局的内部值14来计算在操作符级上应用的另一个内部极限值17。具体地说,这样的操作符级极限值(称为“内存限度”)141(图2)被保存的共享内存140中,和标识每次查询中每个操作符的、要通过服务器进程120A分配的内存的极限值(或目标值)。因此,服务器进程120A-120Z将内存限度141与(例如,在一遍扫描模式下操作的操作符的)所需内存的估计值142I相比较,以确定要分配的内存,此后,分配适当的内存量(或取决于实现,加以排队)。请注意,在这种实现中,同一内存限度141用于把内存分配给所有操作符,但是在另一种实现中,可以把不同内存限度用于每种类型的操作符(例如,散列连接可以具有与用于排序的相应限度不同的限度)。
估计值142A-142P的每一个被保存在要为其分配内存的操作符的简要表143J中。在一种实现中,许多个简要表143A-143V的每一个被保存在共享内存140中。在这种实现中,进程120A-120Z通过在共享内存140中创建包含操作符需要的三个内存估计值的相应简要表143J,登记每个操作符(参见图1B中的步骤127),以便在如下的三种模式的每一种下操作最佳模式、一遍扫描模式和最小模式。“最佳”模式在本文也被称为“高速缓冲”模式,因为在执行期间操作符不要求盘访问。
此后,进程120I按如下确定要为数据库应用中的排序操作符分配的内存量如果最佳内存估计值142P小于内存限度141,采用最佳内存估计值142P(参见图3中的步骤151-152);如果内存限度141在最佳内存估计值142P和一遍扫描内存估计值142I之间,采用一遍扫描内存估计值142I(图2)(参见图3中的步骤153-154);并且如果内存限度141小于最小内存估计值142I,采用最小内存估计值142A(图2)(参见图3中的步骤155)。使用刚刚所述的分配是因为(与从最小到一遍扫描的内存增加相比)排序操作符不能从一遍扫描估计值到高速缓冲估计值的内存增加中获得一样多的好处。
正如在别处所述的那样,确定待分配内存量的特定方法可能取决于几个因素进程属性(例如,优先级)或操作符。图1B的步骤127是可选的,并且,未必把操作符简要表登记在共享内存140中,在其它实现中,每个进程120A分别把这样的简要表保持在它自己的内存中。
请注意,对于一些操作符,最小内存估计值142A可以大于内存限度141,并且,在一个实施例中,不让这样的进程排队,而是让它们分配最小内存估计值142A,以便进行查询。在这样的情况下,如果其它进程欠分配,即分配小于内存限度141的内存,那么,通过应用分配的总内存可以保持在外部设置全局值11之后。但是,分配大于内存限度141的内存的进程120A-120Z可能超过欠分配的进程,使得总分配内存超过外部设置全局值11并使全局内部值14降低(通过内存中介器115),全局内部值14的降低又使内存限度141降低(也通过内存中介器115)。此后,进程120A-120Z被迫分配比值11保持不变时它们将分配的内存小的内存。这样,在进程120A-120Z之间存在着一些妥协,以便达到外部设置全局值11。如果进程120A-120Z的总数太多例如所有进程的最小内存估计值142A-142Z之和超过值11,那么,不为任何进程分配附加内存,而是排队内存请求。
在一个实施例中,每当如上面参照图1A所述的那样,分配或解除分配内存时,进程120A-120Z还更新有关内存使用的统计表160(图2)。具体地说,统计表160包括已分配但未被使用的内存(称为“空闲内存”)161(图2和4)的数量。例如,进程120I可能需要分配1MB,但是,如果操作系统101只以4MB的增量(例如,由于这是页面尺寸)提供内存,那么,3MB是空闲内存,4MB是分配内存,和1MB是使用内存。空闲内存161(图4)一般说来不可用于任何其它进程120J。
进程120A-120Z还更新统计表160中,与实现查询的操作符(譬如排序、散列连接和位图合并)无关的内存(称为“其它内存”)162(图2和4)的数量。例如,进程120I可以包括与查询实现操作符无关和使用内存162的PL/SQL或JAVA指令序列。一般说来,其它内存162不能通过改变操作符起作用的方式(例如,一遍扫描/多遍扫描)来改变。
进程120A-120Z还保持统计表160中,操作符实际使用的内存(称为“工作区内存”)量163。在一个实施例中,进程120A-120Z对统计表160的维护是在又调用“malloc”和“free”的包装函数(wrapper function)中实现的。此外,对于独立进程120A-120Z的每一个,可以分开保持统计表160,或者可选地,可以保持各个统计表的总表(遍及所有进程120A-120Z)。
在一个实施例中,内存中介器115利用上述的统计表160来以如下方式计算用作工作区内存163的数量的目标值的全局内部值14(在图5中被表示成Ti)。具体地说,内存中介器115首先计算作为使用内存164(在图5中被表示成Um)和工作区内存163(在图5中被表示成Wm)之间的差值的其它内存162(在图5中被表示成Om)。接着,内存中介器115检验(参见图5中的步骤172)外部设置全局值11(也称为“PGA AGGREGATE TARGET”和在图5中被表示成Tpga)是否小于其它内存162,如果是的话,把Ti设置成Tpga的6%。
因此,在最坏可能情况下,当其它内存162的内存太大时,把Tpga的某个最小值(例如,6%)用作全局内部值14。这是因为,其它内存162的尺寸超出了内存中介器115的控制范围。如果其它内存162小于Tpga,那么,在步骤174中,内存中介器115把全局内部值14设置成Tpga和Om之间的差值的90%,然后,转到步骤175。这是作为“安全”措施完成的,以计及在内存中介器115的两个相继操作之间的时间间隔内分配内存的变化(因此,在一个例子中,预期分配内存不会以每3秒钟快于10%地增加)。
接着,在步骤175中,内存中介器115检验分配内存(在图5中被表示成Am)是否大于Tpga,如果是的话,转到步骤176(处理过分配),或者转到步骤177(处理欠分配)。在步骤176中,内存中介器115计算作为比Wm/(Om+Wm)的因子Fwa(也称为“工作区分配因子”),和进一步计算作为比(Am-Tpga)/Am的另一个因子Foa(也称为“过分配因子”),并且把新极限值Ti确定成当前极限值Ti乘以(1-Fwa*Foa)。
在步骤177中,内存中介器115检验Am的90%是否小于Tpga,以及所有最佳内存分配之和是否大于Tpga,如果是的话,不改变Ti。否则的话,内存中介器115转到步骤179,以计算上述工作区分配因子Fwa。接着,在步骤180中,内存中介器115计算作为比(Tpga-Am)/Tpga的欠分配因子Fua(也称为“提升因子”)。此后,内存中介器115把新极限值Ti计算成当前极限值Ti乘以(1+Fwa*Fua)。接着,内存中介器115把新计算的极限值Ti和Tpga的6%的较大者设置成(在步骤182中)像在本文所述那样使用的全局内部值14。
具体地说,将来,新计算的全局内部值14用于分配各种操作符所需的内存。正如本文在别处所述的那样,这样的全局内部值14可以直接供(为每个独立操作符分配内存的)进程使用,或者可以用于计算又供这样的进程使用的内存限度。在一个特定实施例中,从所附附录中的伪码中如下所述的全局内部值14中计算内存限度17。
通过使用例如可以设置成两个值AUTO和MANUAL之一的、可以称为“WORKAREA_SIZE_POLICY”的数据库参数,可以与现有技术的人工机制结合在一起使用如本文所述的内存自动和动态分配。把这个参数设置成AUTO调用自动和动态分配。此外,可以实现另一个数据库参数PGA_AGGREGATE_TARGET(如上所述),并且,当数据库参数PGA_AGGREGATE_TARGET被数据库管理器设置时,参数WORKAREA_SIZE_POLICY的默认值被自动设置成AUTO。
或者,当PGA_AGGREGATE_TARGET未被设置时,参数WORKAREA_SIZE_POLICY的值被自动设置成MANUAL。如果参数WORKAREA_SIZE_POLICY的值被设置成MANUAL,那么,在这个实施例中,不使用PGA_AGGREGATE_TARGET,而是数据库使用现有技术机制(例如,利用数据库管理器对每个操作符的内存设置的各自目标值)。
可以将自动和人工机制组合在一起,以保持例如向后兼容性一些操作符可以使用人工机制,而另一些操作符可以使用自动机制。在这样的组合操作中,全局内部值14自动降低,以适应人工机制使用的内存。
取决于内存使用,内存中介器115可以在操作符分配内存之后马上降低内存限度例如如果进行查询的次数突然增加的话。相反,如果对内存的要求降低了,内存中介器115可以提高内存限度17。在已经计算出内存限度17的新内部值之后,在一个特定实施例中只把值17应用于打算在计算之后,分配内存的新操作符。在另一个可选实施例中,内存限度17这样的新值也供以前已经分配了内存和当前正在执行的操作符使用,从而在执行期间减少(或增加)它们以前分配的内存。
操作符对内存限度17发生改变的响应可以影响内存中介器115在给定区间内重新计算内存限度17的次数和/或内存限度17的改变量。例如,如果当前正在执行的操作符不敏感或响应缓慢(与内存中介器115的响应相比),那么,内存中介器115重复地降低全局内部值14和内存限度17,以便保证总分配内存接近外部设置全局值11的目标值。
为了在分配内存之后,对内存限度17的改变作出响应,操作符可以在它们执行期间的方便点上检验内存限度17(或全局内部值14)的改变。检验内存限度17(或全局内部值14)发生改变的点可以同步(例如,每秒一次)或异步(例如,在操作符执行期间完成了一个或多个步骤之后)设立。在这两种实施例中,操作符将它们的模式例如从最佳改变成一遍扫描,或从一遍扫描改变成最小,因此,取决于内存中介器115所作的决定,改变它们的分配内存。此外,这样实施例的操作符可以在它们的操作期间,动态地修改它们内存要求的估计值。下面简要讨论在执行期间对散列连接操作符的修改和对排序操作符的修改,以实现模式的改变和分配内存的改变。
在一个实施例中,AUTO方式(如上所述)的散列连接操作符登记有关它工作区的信息(例如,存储在如下三种模式的每一种下要求的内存估计值最佳模式、一遍扫描模式和最小模式)。在这个实施例中,每个操作符的称为“mode”的变量(驻留在SGA中)指示操作符的操作的当前模式,因此,指示它的内存使用。在这个实施例中,每个操作符的“mode”变量只被这个实施例中的操作符改变(但是,在另一个可选实施例中,内存中介器115可以作出这样的改变)。
只要内存限度17足够高,散列连接操作符就可以在最佳模式下操作,和散列连接操作符分配初始内存量和动态地增加它的内存(直到最佳模式估计值),以存储输入行。但是,即使在最佳模式下操作,散列连接操作符也根据一遍扫描要求划分输入数据,以便如果内存限度17降低了,允许切换到一遍扫描模式。在这个实施例中,当在内存中构建时,如果充分地降低内存限度17,使模式从最佳改变成一遍扫描,那么,散列连接操作符通过把适当的数据量清仓到盘上,把它工作区的尺寸调整成一遍扫描要求。
在一遍扫描模式期间(在构建阶段),散列连接操作符以正常方式工作。但是,工作区的尺寸被调整成包含一个构件分区加上每个附加分区一个或多个IO槽(以支持异步输入和输出)。在这个阶段,即使输入比所预期的大得多,也不调整工作区的尺寸。散列连接操作符只使用在开始构建时为一遍扫描模式估计的内存量。
一旦第一个一遍扫描构件(是第一构件)完成了,构件的每个分区的尺寸是已知的。如果最大分区的实际尺寸是每个分区的预期公共尺寸(例如,一遍扫描尺寸)的两倍或更多倍,散列连接操作符就利用来自第一构件的行,重新构建。重新构建步骤使用精确的尺寸来确定构件分区的理想个数,因此,确定工作区内存的更精确估计值。
构建第二构件快于构建第一构件(在大多数情况下),因为在重新构建期间的输入数据尺寸小于原始数据尺寸,并且,一般说来,与探查时间相比,构建时间是非常短的。此外,当与散列连接操作符的总执行时间相比时,额外重新构建时间可忽略不计,因为探查时间要长得多。但是,从这样的重新构建中节省下来的内存也许极大(如果估计输入尺寸造成的误差重要的话)。
只要内存限度17高到允许以“高速缓冲”(也称为“最佳”)模式执行,散列连接操作符将在内存中探查。如果充分地降低内存限度17,使模式改变成“一遍扫描”,那么,通过调整它散列区的尺寸,散列连接操作符将切换到一遍扫描探查。那时,将一小组分区清仓到盘上,和从留在内存中的分区开始以一遍扫描模式继续进行探查(probe)。以后,在把内存限度17修改成低于一遍扫描估计值的情况下,把当前保留在内存中的所有构件分区清仓到盘上。然后,根据最小要求(例如,每个分区2个槽)划分探查。
对于每对构件/探查分区,散列连接操作符分配足以把两个分区的较小者高速缓存在内存中的内存。由于存在潜在的额外重新构建阶段,即使输入尺寸估计值是不正确的,也应该使消耗的内存接近理想一遍扫描内存要求。
在“AUTO”方式(如上所述)下运行时对排序操作符所作的修改与对散列连接操作符所作的修改类似。排序操作符能够在任何时间点从最佳模式切换到一遍扫描模式。排序操作符还按输入尺寸渐进地增加计及不良估计值的每个排序行程的尺寸。那样,排序操作符总是进行内存增加不多的一遍扫描合并。
在一个实施例中,当排序操作符估计的工作区超过预定值(譬如128KB)时,排序操作符登记它的工作区简要表(包括估计值)。小于等于预定值的估计值不登记,以便在联机事务处理(OLTP)环境下,限制使用内存中介器115造成的影响,与其它环境相比,在OLTP环境下对排序操作符的输入在多半时间里是非常小的。因此,可以避免对于很小的工作区涉及到内存中介器115。
排序操作符的最佳模式与MANUAL(如上所述)方式的排序操作符类似。把从底层行源中取出的行加入排序操作符的工作区中。工作区的尺寸以缓慢的方式增加。如果在某个点上内存要求高于最佳内存估计值(例如,输入大于预期的值),更新三个估计值的一个或多个。只要内存限度17足够高,允许为当前执行分配最佳内存估计值,即使该要求高于开始排序时得出的初始最佳内存估计值,排序操作符也继续扩展它的工作区。
如果在某个点上内存限度17降得足够低,使模式从最佳改变成一遍扫描,排序操作符就把当前和第一排序行程清仓到盘上。然后,排序操作符使工作区收缩到当前一遍扫描内存估计值。那时,排序操作符切换到一遍扫描模式。
在一遍扫描模式下,排序操作符按输入尺寸动态地扩展计及不良估计值的工作区。例如,让我们假设真正的输入尺寸是800MB,而不是100MB(相差8倍)的预期尺寸。当排序操作符开始生成它的第一组排序行程时,它根据估计的100MB输入尺寸调整工作区的尺寸。在采用64KB IO尺寸的情况下,这给出了2.5MB的工作区尺寸。一旦输入的100MB已经用完,这相当于40个行程,排序操作符就通告需要排序更多的行。那时,排序操作符假定估计输入尺寸相差2倍,它将采用200MB的估计值,而不是100MB。根据这个新估计值,由于一遍扫描所需的内存随输入尺寸的平方根而改变,所以通过将它的实际尺寸乘以因子sqrt(2)调整工作区的尺寸。不断地重复同一技术,直到来自输入的所有行都用完为止。
在该例子中,可能存在对于第一个100MB,每一个为2.5MB的40个行程(run);然后,对于下一个100MB,每一个为3.5MB的29个行程;对于下一个200MB,每一个为5MB的40个行程;最后,对于最后一个400MB,每一个为7MB的56个行程。在排序操作符的第一阶段结束时,总共存在165个行程,而不是当从一开始就知道输入尺寸是800MB时将获得的114个行程的“理想”个数。在一遍扫描操作中利用10.3MB(165×64MB)的合并区合并这些行程。这是比理想个数是128的行程的一遍扫描合并所需的8MB(128×64MB)稍大一点的内存。
一般说来,假设与真正输入尺寸S相比,对排序操作符的输入的估计尺寸Sestim至多相差一个因子2n(即,2n-1S<Sestim<=2nS),可以证明排序行程的最后个数Nfinal将是(((1-1/2n)(2-2))+1/2n)N]]>其中,N是对于真正尺寸(real size)S,行程的理想个数(即,N=sqrt(S/C))。在上面的例子中,由于相差8倍,因此n是3。利用上面的公式,本领域的普通技术人员可以计算出排序操作符将生成1.45倍的理想一遍扫描的行程的个数。这意味着一遍扫描合并阶段将消耗1.45倍的理想一遍扫描内存。当n是1(相差2倍)时,这个因子是1.2,和当n无穷大时,这个因子收敛到等于1.7的1/(2-sqrt(2))。因此,在最坏情况下,额外内存消耗在合并阶段被限制在1.7倍的理想要求上(采用已知的输入尺寸)。此外,如果考虑到在整个排序操作期间的内存消耗,由于利用比理想内存小的内存生成行程,所述额外内存消耗稍微小一点。
如果没有这种技术,进行一遍扫描合并将要求比用于一遍扫描合并的内存大2n倍的内存。就内存消耗而言,由于合并扫描的持续时间与行程的个数成正比,甚至比这种情况更坏。如果不动态地修改工作区的尺寸,排序操作符将生成许多(小的)行程,从而使合并阶段的持续时间延长。
就公开的文本而言,本文所述的实施例和实现的许多修改和改进对于本领域普通技术人员来说是显而易见的。例如,在查询的执行完成之后,可以保存专用于查询的统计表,供需要再次执行非常相同的查询(例如,由另一个进程)时进行估计用。
此外,如果所有有效操作符都用完它们的最小内存和假设有更多的内存可用,那么,内存中介器可以把那个内存首先分配给从内存增加中获得好处最多的操作符。例如,可以把内存中介器编程成把更多的内存给予散列连接操作符,使它的响应时间从5分钟减少到1分钟(加快了5倍),而不是把相同的内存量给予另一个散列连接操作符,使它的响应时间从1小时减少到30分钟(只加快了2倍)。因此,一个实施例考虑到响应时间加快,而不是真正考虑绝对时间提高。此外,在在共享内存(而不是专用内存)中分配操作符所需的所有内存的数据库中,也可以像本文所述的那样使用内存限度。
因此,本文所述的实施例和实现的许多这样的修改和改进都包括在所附权利要求书中。
附录<pre listing-type="program-listing"><![CDATA[  Initialization  workarea_left=work areas of all operations active in the system  number_of_workarea_left=number of work areas active in the system  memory_target=the global internet target or limit to distribute among theactive work areas  Memory Bound Computation  /* This while loop terminates once all work areas are removed from  ** the set of active work areas or all the memory has been consumed.  */  WHILE(memory target>0 and number_of_workarea_left>0)  {  /* compute an initial value of the memory bound assuming that each work  ** area will consume bound.Some of them might consume less than this so  ** the final memory bound might be higher than this initial value.  */  memory_bound=memory target/number_of_workarea_left;  /*Loop over all operations left in workarea left,i.e.,that have not  ** been assigned a memory size to use during their execution.  */  removed=FALSE;/* no one has been removed so far */  FOR EACH(workarea(WA)in workarea_left)DO  {  /* Compute the size of the memory it can use based on the memory_bound.  ** Also compute the memory increment it will take in case we are willing  ** to give it more memory.  ** This memory increment is operation-dependent.  ** Hash-Join,the next memory increment can be anything,while for Sort,** it will be the memory requirement of a higher mode.That’s if current  ** memory usage corresponds to one pass the next memory increment is the  ** memory necessary to move to optimal mode requirement.  ** The reason is that the Hash-Join operation performance will improve  ** linearly from additional memory while the Sorr doesn’t.  get_memory_profile(INWA,JNmemory_bound,   OUTmemory_used,OUTnext_increment);  /* Memory used is equal to the memory requirement to run in optimal mode  ** which means that the memory_bound is greater than that requirement.  ** This operation has the maximum memory size it can hope for,so we’ll  ** take it off the list of left work areas.  */  IF(memory_used=optimal memory)  {  memory_target-=memory_used;/*this much is consumed */  workarea_left-={WA};/* remove it from the set */  number_of_workarea_left--;/* one less */  removed=TRUE;  }  ELSE  /* We keep this work area for now,and check whether it’s the largest  ** one in the set,in which case we keep a tag on it.  ** Such a work area is the best candidate to eliminate relative to the  ** ones left  ** Once this loop is over we will eliminate it from the set.  */  /* In case we didn’t remove any work area during the previous loop */  }  IF((NOT removed)AND max_next_memory<memory_used+next_increment)  {max_next_memory=memory_used+next_increment;  largest_wa=WA;  memory of_largest wa=memory_used;  }  }  }1* end of FOR EACH LOOP */  /* All work areas have got their best hope for memory size,then we are  ** done.  */  IF(the memory used by each WA is equal to the bound)  {  number_of_workarea_left=0;  }  ELSE  /* We couldn’t remove one work are */  IF(removed==-FALSE)  {  /* remove the largest a work area,take off the largest one */  workarea_left-={largest_wa};  memory_target-=memory_of_largest wa;  number_of_workarea_left--;  }  }]]></pre>
权利要求
1.一种在计算机中将内存分配给与数据库有关的数个进程的方法,该方法包括存储要分配给进程的总内存量的第一值;和根据第一值,导出要由至少一个进程中的至少一个操作符分配的内存量的第二值。
2.根据权利要求1所述的方法,还包括按第二值的数量分配内存;根据第二值改变第一值;在改变第一值之后重复导出步骤。
3.根据权利要求1所述的方法,还包括按第二值的数量分配内存;和不改变第一值地重复导出步骤。
4.根据权利要求1所述的方法,其中所有进程都可以访问计算机中的共享内存;和该方法包括把第二值存储在共享内存中。
5.根据权利要求4所述的方法,还包括在共享内存中存储要供一个操作符使用的内存估计值。
6.根据权利要求5所述的方法,其中所述估计值具有一个操作符所需的内存。
7.根据权利要求4所述的方法,还包括对于每个操作符,每个进程在共享内存中存储最佳模式所需的内存的第一估计值;一遍扫描模式所需的内存的第二估计值;和最小模式所需的内存的第三估计值。
8.根据权利要求7所述的方法,还包括将第二值与估计值的至少一个相比较;和根据比较结果确定要分配给操作符的内存量。
9.根据权利要求4所述的方法,还包括每个进程根据第二值分配内存;和每个进程在共享内存中存储分配给该进程的内存量。
10.根据权利要求9所述的方法,还包括每个进程在共享内存中存储该进程中每个操作符使用的内存量、该进程的其它部分使用的内存量和已分配但没有被该进程使用的内存量。
11.根据权利要求1所述的方法,其中计算机包括不受这些值约束的附加进程。
12.根据权利要求1所述的方法,其中第二值是所有进程中所有操作符公用的。
13.根据权利要求1所述的方法,还包括周期性地重复确定步骤。
14.根据权利要求1所述的方法,还包括对被分配给数个进程的内存超过达预定数的第一值作出响应,重复确定步骤。
15.一种在其中存储着数个指令序列的计算机可读媒体,该数个指令序列包括当被计算机执行时,使计算机完成权利要求1所述的方法的指令序列。
16.一种在载波媒体中具体化和利用数个指令序列编码的信号,该数个指令序列包括当被计算机执行时,使计算机完成权利要求1所述的方法的指令序列。
17.一种在计算机中将内存分配给与数据库有关的数个进程的方法,该方法包括将要分配给操作符的内存的预定值与如下三个估计值的至少一个相比较操作符的最佳执行所需的内存的第一估计值、操作符的一遍扫描执行所需的内存的第二估计值和操作符的最小执行所需的内存的第二估计值;和根据比较结果导出要分配给操作符的内存量。
18.根据权利要求17所述的方法,其中如果第一估计值小于预定值,把该内存量确定成第一估计值。
19.根据权利要求17所述的方法,其中如果预定值在第一估计值和第二估计值之间,至少从第二估计值中导出该内存量。
20.根据权利要求19所述的方法,其中还从该进程相对于其它进程的优先级中导出该内存量。
21.根据权利要求17所述的方法,其中如果预定值在第一估计值和第三估计值之间,至少从预定值中导出该内存量。
22.根据权利要求17所述的方法,其中如果预定值小于第三估计值,从第三估计值中导出该内存量。
23.根据权利要求17所述的方法,还包括,在比较步骤之前根据要分配给进程的总内存确定预定值。
24.一种在计算机中把内存分配给数个进程的方法,该方法包括每个进程在计算机的共享内存中存储该进程所需的内存量的估计值;每个进程将该估计值与从共享内存中检索的值相比较;和每个进程根据比较结果分配内存。
25.根据权利要求24所述的方法,其中每个进程与数据库有关;和该估计值和该值是用于实现数据库查询的操作符的。
26.根据权利要求25所述的方法,其中每个进程为操作符执行的相应数种模式存储数个估计值;和如果第一估计值小于该值,把在分配步骤中分配的内存确定成第一估计值。
27.根据权利要求26所述的方法,其中操作符是排序;和如果该值在第一估计值和第二估计值之间,把在分配步骤中分配的内存确定成中间估计值,其中,中间估计值在第一估计值和第二估计值之间。
28.根据权利要求26所述的方法,其中操作符是散列连接;和如果该值在第一估计值和中间估计值之间,把在分配步骤中分配的内存确定成该值,其中,中间估计值在第一估计值和第二估计值之间。
29.一种在计算机中将内存分配给数个进程的方法,该方法包括每个进程将实现数据库查询的操作符所需的内存估计值与预定数字相比较;和每个进程根据比较结果分配内存。
30.根据权利要求29所述的方法,其中,预定数字指的是可用于分配的内存,该方法还包括当预定数字超过估计值时,进行分配;和如果估计值超过预定数字时,使进程排队。
31.根据权利要求29所述的方法,其中,估计值具有操作符的最小模式所需的内存,并且,其中即使估计值超过预定数字,也进行分配。
32.一种在计算机中将内存分配给数个进程的方法,该方法包括存储与要分配给进程的总内存有关的第一值;从第一值中导出第二值;利用第二值为一个进程分配内存;和在所述利用之后修改第二值。
33.根据权利要求32所述的方法,其中,所述修改提供修改第二值,和该方法还包括利用修改第二值为另一个进程分配内存。
34.根据权利要求32所述的方法,其中所述修改第二值是从所述第二值和所述第一值的每一个中导出的。
35.根据权利要求32所述的方法,其中所述修改是周期性地进行的。
36.根据权利要求32所述的方法,还包括每个进程更新与内存的分配和解除分配有关的内存使用统计表;和将该统计表与第一值和第二值的至少一个相比较;其中,修改是基于比较结果的。
37.根据权利要求36所述的方法,其中每个进程进行比较和对结果作出响应引发修改。
38,一种执行与数据库有关的数个进程的计算机,该计算机包括存储要分配给进程的总内存量的第一值的装置;和根据第一值,导出要由至少一个进程中的至少一个操作符分配的内存量的第二值的装置。
39.根据权利要求38所述的计算机,还包括按第二值的数量分配内存的装置;和根据第二值改变第一值的装置。
40.一种执行与数据库有关的数个进程的计算机,该计算机包括将要分配给数据库操作符的内存的预定值与如下三个估计值的至少一个相比较的装置数据库操作符的最佳执行所需的内存的第一估计值、数据库操作符的一遍扫描执行所需的内存的第二估计值和数据库操作符的最小执行所需的内存的第二估计值;和与比较装置耦合以从中接收比较结果、导出要分配给数据库操作符的内存量的装置。
41.根据权利要求40所述的计算机,还包括存储三个估计值的装置;和其中,所述导出装置包括如果第一估计值小于该值,选择第一估计值的装置。
42.一种将内存分配给在其中执行的数个进程的计算机,该计算机包括存储与要分配给进程的总内存有关的第一值的装置;从第一值中导出第二值的装置;利用第二值为一个进程分配内存的装置;在所述利用之后修改第二值的装置;和利用修改第二值为另一个进程分配内存的装置。
43.根据权利要求42所述的计算机,还包括更新与内存的分配和解除分配有关的内存使用统计表的装置;和将该统计表与第一值和第二值的至少一个相比较的装置。
全文摘要
应用程序(如数据库)对为应用程序执行的函数(function)(如查询)定义要供应用程序使用的内存量的值(也称为外部设置全局值)敏感。在一个实施例中,指令序列(也称为“内存中介器(memory broker)”)利用外部设置全局值来计算以后当分配内存时使用的一个或多个内部值。内存中介器根据为函数分配的内存动态地修改内部值,从而形成反馈回路。
文档编号G06F9/46GK1561486SQ02819443
公开日2005年1月5日 申请日期2002年9月30日 优先权日2001年10月1日
发明者贝努特·达格维尔, 穆罕麦德·蔡特 申请人:甲骨文国际公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1