详细描述
概览
作为以下内容的路标,首先描述各实施例的概览,然后更详细地讨论示例性的、非限制任选实现来提供补充的上下文和理解。然后,描述关于用于对大量数据打包的基于列的编码技术的一些补充上下文,包括经由混合压缩技术自适应地在行程长度编码的性能益处和位打包的性能益处之间进行折衷的实施例。最后,描述其中可实现或部署各实施例的某些代表性计算环境和设备。
如在背景中所讨论的,特别地,由于当前压缩技术的限制、网络上的传输带宽的限制以及本地高速缓冲存储器的限制,常规系统不足以处理在存储器内非常快地从服务器或“云”中的其他数据存储读取巨大量的数据的问题。该问题在各种具有实时要求的不同数据密集型应用执行许多查询时变得复杂,并且蕴含了对大量数据的过滤和/或排序的查询由于此类运算的成本而提出了一个独特的挑战。
在这一点上,如结合此处的各实施例所描述的,通过完全不对任何行进行排序,或者通过仅对与关联于数据窗口的大小的行数相一致或小于该行数的非常少量的行进行排序,避免了涉及对高百分比的行或所有行的昂贵排序的情形。外部查询请求可被拆分成两个不同的内部子请求,其中第一个子请求对于任何指定的WHERE子句和ORDER BY列计算关于行分布的统计量,而第二个子请求基于该统计量来仅选择匹配该窗口的行。
在这一点上,出于稍后对数据进行窗口化的目的充分利用了取决于WHERE和ORDERBY动态获得的统计量。在某些实施例中,为了最小化统计量构建时间,在为了方便直方图构建而被离散化之后,为真实数据或为合成数据值构建统计量。在这一点上,合成(“离散化”)数据被作为一种形式的联接列来对待以便参与ORDER BY运算。
另外,符合以下更详细描述的实施例,一旦分析了ORDER BY运算所蕴含的列的内容,在以O(n)进行第二次扫描之前,不生成最终窗口。此外,在某些情况下,该方法使用预先计算的分层结构数据来模拟某些类型的合成(“离散化”)列。在一个实施例中,一种算法基于查询定义、从统计量中确定的最终窗口的内容、以及并行化程度来选择用于给定数据的合适的离散化方法以及缓存策略。
此外,此处提出了一种用于基于WHERE和ORDER BY桶的内容以及从统计量中确定的最终窗口的内容来选择投影方法的算法。并且,提供了一种用于仅使用对一至最多N(例如,三个)预配置桶的插入来并行地构建最终窗口的方法。在其他实施例中,描述了一种用于在投影期间使用的、根据查询指定、所选离散化方法、如直方图所确定的最终窗口中的数据分布、以及应用于数据处理的并行化程度来配置内部缓存,例如缓存大小及其策略的过程。
关于并行处理,分段离散化允许对没有ORDERBY(只有WHERE过滤)的查询或对匹配尖峰的窗口并行地以O(1)的时间来填充最终窗口。并且,在各实施例中,应用智能缓存方法来以O(1)丢弃将不出现在最终窗口中的行。另外,各实施例任选地产生加窗的行(line)上的迭代程序,来用于流化(stream)所有投影的列的目的。
作为对非限制过程的介绍,图1示出了用于典型查询的执行流程的概览。在接收到查询指定之后,系统在100处分析该查询。这可涉及在110处根据分析所选择的方法来离散化数据。在120,在数据上计算直方图。在130,使用直方图分析该查询指定所蕴含的数据窗口,作为其结果,数据缓存140准备好通过对加窗缓存150、152、154和156进行扫描和填充来并行处理。在160合并缓存结果,并相对于要显示的窗口来修剪结果,且如果满足特定条件,则在170对最终窗口执行局部排序,但仅在需要时才执行。然后输出行号(line#)迭代程序180。
具有过滤/联接运算的基于列的查询处理
如在概览中所提到的,可向大量数据应用面向列的编码和压缩来压缩且同时组织数据以使得稍后对数据的扫描/搜索/查询运算显著地更高效。因此,在各实施例中,这一般是通过将外部查询请求拆分成两个不同的内部子请求来实现的,其中第一个子请求对于任何指定的WHERE子句和ORDER BY列计算关于行分布的统计量,而第二个子请求基于该统计量来仅选择匹配该窗口的行。在这一点上,此处描述的技术可用于任何查询应用来提高查询结果向最终应用或用户(即已排序和过滤的行上的窗口可有益于的任何应用)的递送速度。
更详细而言,一旦查询请求到达存储层,分析该查询请求,且如果查询不包含任何ORDERBY或WHERE子句,则通过返回SKIP & TOP指定的物理行来直接针对存储解析该查询。如果行被过滤和/或排序,则第一步是确定是否能构建任何统计量来帮助标识窗口的内容的本质。
此时,还可确定是否可在包含真实数据的列上构建这些统计量,或者是否需要在合成(“离散化”)列上构建这些统计量。该离散化步骤例如通过允许标识每一线程将产生最终窗口中的多少行,或者通过在数据尖峰上产生窗口的同时最小化存储器和时间成本,来帮助例如在已排序列中的不同数据ID(DataID)的数量较大的情况下最小化构建统计量的成本,或者在没有指定ORDERBY时最小化并行加窗期间的存储器分配成本。该离散化函数一般可被视为已排序列和物理段的函数:fn(已排序列,物理段)
可使用的某些类型的离散化包括对同一组中的相邻的已排序值进行聚类,按照其中经过滤的数据传递WHERE子句而没有设置ORDERBY的段来离散化,以及通过将尖峰拆分成不同(按段)的组来离散化。一旦选择了一离散化函数(如果有的话),则然后执行内部查询,该内部查询的一般形式为:
SELECT fn(已排序列,物理段),COUNT()
FROM...
WHERE用户指定的谓词
该查询返回描述每一值在已排序列上的出现次数,或者如果插入离散化函数的话,描述每一离散化值的出现次数。
在这些结果上,可以构建直方图,例如,x轴包含已排序的组ID(GroupID),且y轴包含先前的组的出现的移动和(running sum)。术语“和”此处有时被缩写为∑。
注意,对于组ID的排序,并非需要对所有现有的行进行排序,甚至不需要对所有不同的数据ID进行排序,因为多个数据ID可通过离散化为相同的组ID而匹配。并且,通过考虑用于存储数据的编码方法,和/或使用预先计算的有序存储(“分层结构”),可确定某一组的位置而不用比较值本身。
此处,已经获取了告知每一组在最终虚拟行集中的位置的有价值的统计量,例如直方图数据。任选地,该信息可被高速缓存来用于以后的使用。接着,可将指定的窗口位置与直方图中的数据进行比较,并且可确定已排序的列上的哪些值将存在于该可见窗口中。
一旦理解了这一点,生成第二内部查询,该第二内部查询一般形式为:
SELECT行号SKIP经调整的跳过TOP经调整的顶部
FROM...
WHERE用户指定的条件AND已排序的列中的值=从直方图确定的值
ORDERBY用户指定的已排序的列
USING直方图
在内部,可在多个线程上并行执行的该查询使用跟踪最终窗口的数据高速缓存数据结构。该数据高速缓存基于查询指定、所传递的直方图、窗口的位置、所使用的离散化的类型、以及应用于处理的并行化程度来确定其配置。填充最终窗口的请求因此可在可能多个处理器上并行执行,每一处理器扫描不同的段(所涉及的列的部分)并部分地完成最终结果集。在这一点上,可取决于上述数据高速缓存配置来使用各种缓存类型。
对这些缓存的插入是O(1),它们之间的不同在于其策略。完成插入的方式以及选择某一缓存还是另一缓存的决策基于缓存配置以及关于所扫描的当前桶(桶是当前在所涉及的WHERE和ORDERBY列中扫描的片段)内的内容的纯度/非纯度的元数据。作为一示例,可分析该关于ORDERBY列上的纯度的元数据,并且如果进行了ORDERBY的值对于桶的整个长度不改变,则可对整个桶做出什么是其中将记录合格行号的正确缓存的确定。或者,如果该元数据指示WHERE条件对于整个桶的长度不改变,则可用相同的方式来对待该桶中的所有行(line)(或者有资格或者没有资格被添加到桶)。
某些类型的缓存用作仅仅插入客户机所请求的任何内容的“普通”缓存,而其他一些缓存则丢弃在给定阈值之后插入的尝试,另外一些缓存则以循环/环形缓存的方式来盖写现有记录。这些缓存所使用的大小和策略是在配置数据高速缓存时选择的,并且使得最终窗口能以O(n)的扫描时间被填充,同时充分利用所有的处理器,即,使用并行执行。
在该查询的结束,可存在一个或多个数据高速缓存,如果有多于一个段和多于一个处理器可用则可存在更多,且数据高速缓存包含了转变为最终窗口的所有行号,这可能比确切数量要多一点。然后,应用修剪,即,通过使用直方图以O(1)来完成对额外行号的消除。在许多情况下,保持行号的剩余记录可能不需要额外的排序,因为它们或者是以自然次序的(由于扫描各段时的固有次序),或者可在流输出(stream out)结果时在进行中进行多重合并(multi-merge)。然而存在仍然需要对经修剪的结果进行排序的某些情况,例如对于通过聚类进行的离散化,或者在中间缓存中分配多个值的情况下,但是这一排序成本即使是在最昂贵的情况下也总是小于对整个表进行排序的成本,因为该排序是有限的并且与可见窗口的大小相关。对于典型的加窗情形,可见窗口的大小将比表中可存在的行数小许多数量级。
所产生的加窗信息然后使用返回合格行(行号)的枚举器来展示给外部层,该枚举器被用作产生最终行集时的主驱动器。
由此,在各实施例中,可处理用户界面组件或其他界面所生成的查询,以便请求特定数据窗口,对窗口应用过滤,并对其进行排序。在这一点上,在一个非限制实现中,为了提高性能,添加加窗支持作为数据和响应查询的请求应用之间的层,如:
SELECT
[SKIP<整数>]
[TOP<整数>]
[DISTINCT]<列的列表>
FROM<表>[NATURAL_JOIN<表>][NATURAL JOIN<表>...]
WHERE<过滤条件>
[ORDER BY<列>[ASC|DESC][,<$行号>[ASC]]]
在一典型的情形中,数据消费系统或应用使用到查询处理程序和处理器的接口,该查询处理程序和处理器代表数据消费者对数据进行高效的探查、过滤和排序,并返回满足该查询的数据窗口。尽管可支持异步查询运算,但期望实际查询能相对快速地完成。
例如,在一示例情形中,用户或应用可能面对具有数十亿行的表,并且希望对该表进行查询。例如,用户可应用过滤,并且还可按一列来进行排序。采用以下更详细描述的各实施例,用户可以在几秒内检索满足该查询的适当的数据窗口。一旦检索出该窗口,用户可经由暗示附加查询的UI组件来向下滚动,此时仅在半秒内就返回数万行的后续窗口。
关于某种命名法,任选地,可使用被优化来保持聚集结果的数据高速缓存数据结构。作为一简化示例,“方”数据高速缓存可被组织为在一侧具有销售人员ID且在另一侧具有产品ID作为坐标的二维数组,并且在每一单元内保存聚集的值(例如,销售人员对产品所做出的销售总额,其中销售人员和产品由该单元的坐标来标识)。在该示例中,没有与该数据高速缓存内的聚集值相关联的固有次序。
如此处所使用的,查询核指的是被优化来响应涉及聚集和过滤的公式引擎请求的分量,其从逻辑观点来看等价于以下SQL查询:SELECT<列>,<聚集>FROM<表>WHERE<谓词>GROUPBY<列>。查询核被设计成返回数据高速缓存,因为这是较高层能在其上对各种核心场景高效操作的最优结构。
如此处所使用的,行集(rowset)指的是包含可以用到查询处理组件的接口来看见的项的一组数据、多个行、多个列。例如,行集可包括被表示为按照销售人员排序的、包含“销售人员”、“产品”和“收取费用”列的行的所有销售的列表。行集可由服务器来流化,并且其行具有固有次序。
查询指定数据结构描述了查询,并且可任选地用作服务器和存储之间的接口。尽管不是文本格式,但查询指定数据结构可在逻辑上被认为等价于服务器发送到存储引擎的查询。
如以下更详细描述的,行程长度编码(RLE)是通过表述X值在序列中连续出现N次来压缩数据的方法。在以下关于用于大量数据的编码技术的补充上下文的节中描述的打包算法的处理期间RLE压缩是首选的。RLE压缩也在查询核为对数据进行快速聚集和快速过滤而执行的扫描期间被利用,该扫描也在以下对补充上下文更详细描述。在处理期间,在面向列的存储中最大化RLE序列,该RLE序列在最大化在某一列上具有相同值的相邻行的序列时被转换。
一旦诸如但不限于SQL查询等查询被传递给查询引擎,该引擎就解析该查询,将这些查询绑定到内部查询指定,将查询指定传递给查询处理程序,查询处理程序内部地执行处理来返回包含已排序和已过滤的数据的指定窗口的已排序行集。
对于查询引擎和查询处理程序之间的通信,可使用标准客户机-请求接口机制,例如查询客户机请求和响应。所传递的请求包括描述应返回什么数据的查询指定。响应因而包含行集而非数据高速缓存,因为数据高速缓存具有固有次序。
图2是各组件和示例性接口的非限制框图概览。在消费侧,接口组件220处理发出查询202和接收作为结果的行集204。中间层查询引擎210可以通过定义查询指定212并将其一直传递到查询处理程序220的客户机请求处理程序222来准备查询202。客户机请求组件确定查询指定212是蕴含将查询指定224转发到快速无排序访问算法226,还是蕴含将查询指定242转发到基于列的排序算法240。在任一情况下,行集214被返回给查询引擎210以便转发到接口组件200。如上所述,面向列的存储、统计量和其他核心服务组件230处理所请求的数据上的直方图等的生成。基于列的排序240就查询指定238而言与基于列的扫描234协作,并且可任选地在交换方面使用轻量数据高速缓存236。其他高速缓存数据结构232也可用于存储临时结果以供稍后重用。枚举器228向使用了快速无排序访问226的地方通知来自核心服务组件230的结果。
在查询处理组件内部,若干选项涉及范围从提供以ORDERBY为目标的完全不同的查询引擎到修改现有的查询核以及添加对查询核内部的排序的直接支持,或混合解决方案。
在这一点上,当查询以查询指定的形式到达查询处理组件时,检查该查询并对其决定执行路径。注意,对于不蕴含排序次序或过滤的简单查询,可直接对存储使用直接的ISAM类型的访问,而对于较复杂的查询,选择关注数据分布并使用查询核或面向桶的排序算法的更复杂的执行计划。
高速缓存可用于存储可在随后用户在UI组件内滚动时被重用的昂贵的中间结果。
为了满足在几秒的时间范围内返回数十亿行上的已排序结果的要求,简单的对所有内容蛮力排序方法在所花费的时间和存储器使用方面的代价太高。
在各实施例中,使用了一种模块化方法,其中某些模块被重复使用,其他模块则在某些情况下被跳过。整个执行流程的一般算法,包括执行了什么模块的完整的端对端概览可在以下详细描述中获得并讨论。
所涉及的模块的高级概览首先在图3中示出。如图所示,最初,在300分析查询指定。然后,在310,在310计算直方图来作为第一步。基于该直方图,在320分析查询所蕴含的局部窗口分布,并且或者选择标准选择330或者选择基于列的排序340来进行处理。在任一情况下,在350,将结果返回给请求应用。
首先,从首先是最简单的特定情况,然后逐渐查看较复杂且一般的情况,来呈现各种情况/情形。在各实施例中,以模块化方式呈现统一的、一般的、端对端算法。任选地,可使用高速缓存来存储某些临时结果以便重复使用。
在这一点上,当接收到查询时,定义被分析的查询指定。一旦客户机查询到达查询处理组件,分析查询指定来找出是涉及不涉及任何排序和过滤的简单查询,还是该查询是需要大量处理的查询。
对于非过滤且非排序查询,例如索引的顺序访问方法(ISAM),如果没有过滤和排序,则可通过使用直接的ISAM型的访问类型来履行该请求而没有开销。这意味着(1)获得所涉及的列上的正确枚举器,(2)在正确的位置进行Goto()(例如,执行SKIP),以及(3)在该数据上构建行集,例如对TOP数量的行执行Next(),解码该值并填充行集。在这一点上,在一个实施例中,解码在查询处理组件级发生,而非返回具有数据ID的行,因为从服务器到查询处理程序的往返以转换数据ID是不必要的。
对于过滤但未排序的查询,这是不带排序的更一般的“过滤且排序查询”的简化情况,执行中的差别在于专用排序运算是不必要的,并且可以使用涉及数据过滤步骤但不涉及排序步骤且在过滤后返回窗口的一般情况。
在这一点上,在一个实施例中,使用例如能够处理多个并行作业的查询核来充分利用现有的面向桶的过滤逻辑,并获得包含形式为(行号,连续行号)的行的多个“轻量”数据高速缓存,对这些多个轻量数据高速缓存执行常见的“合并多个轻量数据高速缓存”算法来寻找真正的(SKIP,TOP)窗口。注意,某些段作业可在一旦发现已经检索到第一个SKIP+TOP窗口时被较早地停止。此处也称为“c行号”(cline#)的连续行号是在列存储内物理上相邻且匹配过滤谓词的行的计数。由此,(行号,c行号)格式描述了匹配谓词且物理上以连续形式存储的数据组块。这些组块可以是数据基于列来压缩且可在对其执行排序运算的列上找到自然RLE序列的事实的副产品。但还要注意,桶的RLE长度不同于c行号,因为c行号处理“已过滤的”组块。
因此,在这多个拆分窗口上,可以按照与简单ISAM情况相同的方式来构件行集。图4是该过程的框图概览。外部查询指定412由服务器400的查询处理程序410来处理,其被转换到内部查询指定435。
包括过滤谓词的查询被转发到查询核,且获得匹配该过滤的连续行的组块,以及它们出现在何处的位置,从这些组块中,计算“所选”窗口而不必在该情况下进行任何排序。
对于未过滤的但已排序的查询,这同样是更一般的“已过滤且已排序查询”(将在以下更详尽论述)的简化情况。在这一具体情况下,不必应用任何实际的过滤,而需要输出已排序的数据。该数据然后根据表达式440由查询核450来过滤,查询核450对基于压缩列的值序列460进行查询。查询核450然后返回包含匹配该过滤的行号和连续行号(c行号)的行430。如上所述,可使用轻量数据高速缓存425来支持处理和合并运算420来形成行集输出415。
在这一点上,注意,已排序列上的分布影响所选的执行计划。此处执行的各种高效过滤和排序运算的简化概览是对一般情况执行相同操作,除了过滤谓词不被推送到查询核之外。在某一时刻,获得包含(已排序列的数据ID、行号、c行号)的行组块,并且使用这些组块来按照对于以上较简单的情况(ISAM和已过滤但未排序情况)描述的相同的方式来构建行集。
对于涉及对大量数据的过滤和排序的查询,如果查询涉及过滤或ORDERBY子句,则确定一执行计划来满足该请求。实际计划取决于数据模式,其因素包括将对其执行排序的列上的数据ID的分布和基数。下节更详细地细查了这一情况,并描述了数据分布和模式如何能影响执行计划。
关于用于已排序列的不同数据分布的执行计划,图5是可能遇到的一列潜在数据分布500、510、520、530。对这些情况500、510、520、530中的每一个的处理在下文中更详细描述,为便于说明以最简单的情况开始,然后一般化到较复杂的情况。在图5中,x轴上是不同的数据ID,而y轴上表示数据ID的频率(有多少重复)。
情况500示出了具有许多重复的分布,例如,具有合理数量的不同数据ID,但没有偏态的情况。这在该情形中一般被称为“好”基数,因为存在合理数量的不同数据ID,每一数据ID具有许多重复,而没有任何极端的“偏态”情况(其中例如一半的值匹配单个数据ID)。
情况500的示例可包括其中与表内的行数相比存在数量少得合理的不同数据ID的均匀、标准分布或任何其他分布,即,1<<|不同数据ID|<<|表内的行数|。“好”基数的一个示例可能是具有最多例如一百万个不同数据ID的表,不包括偏态分布。
可以在这些类型的分布上利用的性质是平均来说一个数据ID被重复多次,并且由此,可跟踪描述对应于每一数据ID的出现次数的统计量(直方图),例如,可存在十亿行,但是仅有一百万个不同数据ID。由此,可以实现将保持已排序数据ID以及出现次数的准确直方图,例如以分层结构处理时间来计算。
在这一点上,注意,该直方图是“已排序的”。结果,可以维护移动和(running sum)而非实际计数,其中计数可以通过查看下一数据ID来计算。如需要,对于反向排序次序,可通过从实际计数中减去物化的移动和来计算反向移动和。以下表I进一步示出了移动和的概念。
已排序数据ID |
移动和 |
72″飞机″ |
0 |
12″客车″ |
300(因为在表中有300个飞机) |
92″小汽车″ |
314(因为在表中有14个客车) |
6″直升飞机″ |
714等等,对一百万个不同数据ID有一百万次 |
表I-移动和的说明
在其中不应用过滤的情况下,使用该准确的直方图,可以确定在未应用过滤的情况下在某一窗口中可见的实际数据ID是什么(从已排序列中)。
例如,考虑以下查询:
SELECT[交通工具],<其他列>
SKIP 312
TOP 5
对以上表I的直方图信息的简单检查告知,对于行312和313,将返回“客车”,而对于行314、315、316,将返回“小汽车”。
关于什么确切的行包含客车和小汽车,这可通过执行以下查询来确定:
SELECT[交通工具],存储行号,<其他列>
WHERE[交通工具]IN(“客车”,”小汽车”)
从该查询中,根据存储行号选取最后两个客车和前3个小汽车。
注意,可执行使用c行号而非<其他列>的SELECT,并且该SELECT在输出行集的流化方面可能更快,但是如果不涉及任何关系,即,如果数据来自没有自然联接(NATURAL JOINS)的单个物理表,则这将表现得更好。还要注意,在其中应用过滤的情况下,这可以在完全没有任何预先计算的直方图的情况下执行,但因为使用查询核在进行中创建某些统计量,它在查询时间上可能稍微慢一点。
对应用过滤的情况的更多细节,描述已排序数据ID及其计数的直方图是不够的,因为它是过滤不可知的。因此,确定哪些是将被显示的实际行。例如,考虑以下查询:
SELECT[交通工具],<其他列>
SKIP 312
TOP 5
WHERE<用户指定的谓词>
首先,谓词不应被直接评估,因为查询核早已具有许多优化来代替这样做,因此谓词被推送到查询核以便对WHERE子句进行评估。
如果然后执行内部查询,如以下查询:
SELECT[交通工具],COUNT()
GROUP BY[交通工具]
WHERE<用户指定的谓词>
然后,接收对每一交通工具保持匹配计数的1坐标(1-coordinate)“标准”数据高速缓存。对数据ID进行排序,并维护其上的移动和。对于示例数据分布,存在总共超过大约一百万个不同数据ID,并且其中的某一些可能将被过滤排除。
此时,如上所述(在未过滤情况中)获得相同的统计量(直方图),主要差别是该统计量现在应用于已过滤的行。采用与未过滤情况相同方式的后续查询将从窗口中带来匹配数据ID的行。主要差别是<用户指定的谓词>被推送到查询核以便处理,如下:
SELECT[交通工具],存储行号,<其他列>
WHERE[交通工具]IN(“客车”,“小汽车”)AND<用户指定的谓词>
这基本上是用于获得(SKIP,TOP)窗口的选择算法的变型,其利用了统计量、查询核和作为VertiPaq的副产物的自然连续序列。注意,获得对已过滤数据的COUNT()(计数)和RUNNING_SUM()(移动和)的替换方式可以是向查询核提供知道该分层结构的列。这可避免后续的排序,然而,其不仅在提供虚拟列方面是实现起来较复杂的,而且在查询核执行期间还涉及随机存储器访问,这将不利地影响性能。
图6是从逻辑角度来看执行了什么来确定实际输出窗口的图形描述。直方图610包括数据ID600和移动和602的列表,它们通过处理链产生高效的结果620,如上更详细描述的。
对于其中对每一数据ID存在极少重复的情况,有许多不同的数据ID,但没有偏态情况。例如,考虑许多不同数据ID的情况,例如十亿行中的一亿-十亿行,就像某人按照交易ID或某一类似的内容来进行排序(例如,许多数据ID,极少重复)的情况一样。该情况中的分布将看上去像图7的分布700,其在y轴上示出出现数且在x轴上示出不同值。
在这一情况中,准确的直方图是不可行的,且对已过滤的COUNT()执行查询核请求并获得巨大的数据高速缓存(许多不同值->高基数->大数据高速缓存)也是不切实际的。
由此,在这一情形中可使用离散化方法,即,将一组连续的数据ID映射(关于其次序是相邻的)到离散的对应物,然后在离散值上构建直方图(统计量)。该概念在以下表II中示出。
表II-离散化的说明
可以同时对组ID计算移动和,如表III所示。
表I-离散化情况中的移动和的说明
使用该离散化,可使用上述相同的算法,除了基本上通过执行以下内部查询在离散的已排序组内获得值的出现次数,而非从查询核获得关于每一数据ID的确切出现次数的统计量(SELECT数据ID,COUNT()GROUPBY数据ID)之外:
SELECT组ID,COUNT
GROUPBY组ID
WHERE<用户指定的谓词>
注意,这是以上对分布很好的平均数量重复所描述的相同算法的一般化,但是首先经历一级间接(离散化阶段)。更具体地,其中数据分布很好的情况只是其中离散化实际是1->1且数据ID==组ID(一个组恰好有一个值)的具体情况。
关于查询核如何对组ID起作用,因为组ID是查询核外部的概念(查询核只能处理数据ID),所以一个一般的解决方案是以“代理”列对外键(FK)->主键(PK)起作用的相同方式向分段查询提供“虚拟列”。该虚拟列返回对应于实际当前存储行数据ID的组ID。
另一解决方案较好地适合其中存在十亿数据ID的情况,该十亿个不同数据ID对应于数字而非串,并且这些可“按值编码”。该解决方案对保持十亿个不同数字的列起很好的作用,但是对保持十亿个不同串的列则不然。
关于十亿个不同串的情况,这意味着查询核内的随机存取存储器在查找期间解析数据ID->组ID,当计算离散组时串比较不是必需的,因为至少在其中可访问该数据集上的分层结构的情况下,数据ID的位置将足以标识组号。一种解决方案是不仅在按照值编码时,而且在按照散列编码时强制“如果v1>v2=>did1>did2”性质。尽管进行这一强制带来了成本,但这一成本是在处理时而非查询时付出的。另外,该方法可具有几个其他好处,包括在使用OR片(通过传递像did>v1 AND did<v2这样的某些内容)时改善查询核的性能,以及通过对分层迭代程序“解物化”并具有像pos=did-XM_DATA_ID_NULL这样的合成函数来改善分层迭代程序的能力。
基本上,按照值的编码使用函数f:值->数据ID,对该函数,以下性质成立:
如果值1<值2
则数据ID1<数据ID2
这是数据ID小于另一数据ID(对于NULL的数据ID被排除)情况下的相反方向,在这一情况下,值也将以相同方式来排序。
这意味着数据ID的相对次序对应于已排序值的相对次序,因此相邻的数据ID可被分组在一起,因为它们对应于相邻的已排序值。不需要任何随机存储器访问的一种分组策略可以是通过应用将数据ID映射到组ID的简单函数来将(最小数据ID...最大数据ID)中的不同数据ID的整个空间划分成相对相等的(数值)间隔:g:数据ID->组ID:
g(数据ID)=数据ID/间隔大小
g-1(组ID)=[组ID*间隔大小,(组ID+1)*间隔大小-1)
其他分组算法和策略可以是基于直方图的,其中在下文描述了在定址确定数据模式的主体的情况下的边界设置。
该离散化因而允许将数据ID的空间压缩成较小的组ID空间,并且对组ID的每一次出现具有较大数量的重复,这将该问题缩减为以上对于良好分布的数据ID的情况所解决的问题。
一旦从查询核获得了关于数据ID的组800的统计量810,如图8的示例性方式中所示,则执行以下形式的查询:
SELECT组ID,COUNT
GROUPBY组ID
WHERE<用户指定的谓词>
在此,SKIP/TOP窗口的匹配是在来自统计量的移动和上完成的,并且接收对其要输出行的实际候选组ID。
该候选组ID(例如,G#12、G#13、G#14)将被扩展成候选数据ID的列表:
SELECT数据ID,行号[,c行号]
WHERE<用户指定的谓词>
AND数据ID IN(....候选数据ID的长扩展列表...)
这是有好处的,因为对于按照值的数据ID(由于已经讨论过的值函数进行的编码的性质),过滤所选数据ID的附加谓词可被重写(以便允许更快速的查询核评估)为:
SELECT数据ID,行号[,c行号]
WHERE<用户指定的谓词>
AND数据ID>=min(G#12中的数据ID)
AND数据ID<=max(G#14中的数据ID)
这一情况下的结果将是一组特殊的“轻量”数据高速缓存,它们适用于容易地对甚至更极端的数据分布情况应用以下描述的排序算法。
注意,对于这一类型的数据模式的c行号可能不需要跟踪,并且可采用不知道连续的数据ID组块的标准排序算法而非基于列的排序。原因是当几乎所有c行号==1时对这些c行号进行跟踪是不必要的开销。理论上的拐点是在已过滤的数据ID的连续组块的平均值是c行号>4的时候,但是实际的限制可能要稍微高一点。在一个任选实施例中,该值可以基于谓词可选择性和/或已排序列的平均RLE行程来估计。
对于具有很少数据ID、但有十亿个重复的尖峰数据分布的情形,考虑在一组十亿行上的[性别]列的数据分布。在这一点上,将获得指示各自具有5亿重复的两个不同数据ID的统计量,如图9的样本分布900所示的。如果碰巧该窗口在边缘上,则将需要对所有十亿行进行排序。即使确定在所选窗口中只有一个不同的数据ID,如果没有过滤或者如果过滤选择性使得几乎所有内容都被包括,则这仍意味着要求该行的后续查询将返回具有5亿行的数据高速缓存。
可在该数据模式上利用的一个性质是那些尖峰数据ID可能按照RLE形式来被压缩。这意味着对其执行排序的列可能具有长RLE行程。因此,同样在不存在过滤的情况中,代替逐行进行排序,可根据基于列的排序来对RLE序列进行排序。由于RLE的能力,期望这要快几个数量级。
然而,如果应用过滤,则排序不能直接基于RLE序列来执行,因为某些行可能不被包括在输出集中。在这一情况下,生成特殊的查询核请求来获得c行号(通过该谓词的连续行组块),并且对组合键(数据ID,存储行号)执行排序同时还跟踪c行号,这将指示在匹配谓词的排序列上有多少行是具有未改变的数据ID的有效行。
图10是将发生什么的逻辑视图。对于男性和女性RLE编码的数据,发送诸如以下的内部查询:
SELECT数据ID,行号,c行号
WHERE<用户指定的谓词>
作为返回,从查询核的观点返回数据高速缓存,但是在内部将插入特殊的“轻量数据高速缓存”(以下更详细描述),这不需要支持聚集,并且将更好地适合涉及对通过过滤的连续行的组块的基于列的排序的接下来的运算,这也将在下文中更详细描述。
对于偏态数据分布,这进而表示存在十亿不同数据ID的最一般的情况,其中的某一些是唯一的(从未重复),但是仍具有一些具有重复的5亿个值的数据ID,例如尖峰数据ID。
图11所示的一个示例分布110包括具有十亿个记录的表,列上的一半值为NULL,且另一半几乎是完全无重复的不同数据ID。例如,某些数据库可具有对应于每一员工的地址,该地址往往是唯一的,但是可能没有对应于一半员工的记录数据,且因此“没有地址数据”值被重复多次。
在这一情况下,针对十亿不同数据ID(使用离散化)的解决方案在处理尖峰时将会有麻烦,并且针对尖峰情况且利用未改变的数据ID的长连续行程的解决方案在处理完全没有重复的数据ID上的窗口时将会有麻烦。基本上,c行号可被传递,但是匹配过滤的所有行序列将具有它们自己的不同数据ID,且因此关注c行号的开销是不必要的。
在这一情况下,该方法是使用对“局部”数据分布适当的执行计划。对于这一情况,全局数据分布不是重要的,但是相反,对于所请求的特定数据窗口数据是如何分布的是重要的。这在图12中示出。如果查询和窗口蕴含了尖峰,则可应用尖峰数据算法。如果蕴含了均匀分布的部分,则可应用离散化技术。
为此,同样,收集直方图和统计量。为了计算分布直方图,执行采样来找出尖峰。在这一点上,期望知道通用数据模式以便选择适当的执行策略。如果已知对于所请求的窗口的候选数据ID涉及在“尖峰”中,例如是否估计的>一百万个重复或其他阈值。
对于执行离散化的情况(当数据ID具有非常少的重复且希望将它们分组在一起),则估计如何拆分相邻的已排序数据ID的组,即,在每一个桶中有多少。一种方式是以相等的间隔来拆分不同数据ID的整个最小-最大空间,并使用依赖于对每一组的固定间隔大小的非常快的数据ID<->组ID转换。
为此,可构建直方图,如有需要,这可以在处理时或在查询时完成。该直方图可以基于或者随机地采样或者检验1/1000左右个值,然后将该直方图估计扩展到整个空间上。该直方图应能够在相对较快的时间内构建(甚至以1/1000的比率,因为十亿行只有一百万次随机存储器访问)。
对这一数据的随机采样还告知给定数据ID是否为尖峰,例如,如果取1,000,000个样本,且在一半的时间找到一数据ID。可跟踪该“尖峰”数据ID的列表,该列表对十亿行应少于100个不同值。另外,可以在做出是否基于c行号来进行排序(例如,所有数据ID不同的情况)的决定之前检查窗口来查看其是否包括该数据ID。
关于VertiSort(垂直排序)或基于列的排序,在上文对偏态分布的讨论期间提到(但它适用于大多数其他情况),为了对十亿行进行排序,利用了数据是根据基于列的值序列来进行VertiPaq处理或压缩(利用已排序和/或已过滤列上的RLE序列/桶)的事实。
在这一点上,知道内部(存储)RLE长度(通过使得查询核不仅返回数据而且还返回关于已过滤数据ID的连续组块的元信息)允许使用这些RLE长度来最小化排序过程。由此,在存在具有未改变值的十亿行的情况中,即使这些行通过过滤来形成组块,也不需要对返回的数据高速缓存进行物理排序。
为使这一情形发生,A)做出查询核中的某些改变,使得它不仅返回数据而且还返回元数据(这实际上是在桶处理级的优化,以避免不必要的扫描,因为这也可以通过在特殊数据高速缓存中进行连续行的聚集来以蛮力方式完成),B)可实现能够跟踪(数据ID)->(行号,c行号)(行号,c行号)...的特殊“轻量数据高速缓存”,这将允许排序运算的复杂度从n*log(n)(其中n是行数)降低到m*log(m)(其中m是窗口中的不同数据ID的数量),和/或C)实现“轻量数据高速缓存”的特殊聚集,其允许同一处理器对不同的段重复使用的数据高速缓存进行快速原地合并,以及当聚集由查询核产生的所有“轻量数据高速缓存”时在最终步骤期间的快速多重合并。
图13是产生已排序数据上的窗口时所涉及的组件栈的代表性视图。这包括服务器1340接收且由查询处理程序1350处理的查询指定1300,其可生成已过滤数据上的索引1360,包括行号、c行号和移动和。在这一点上,自底向上沿着处理链,在应用基于列的扫描1320期间利用基于列的压缩1330。如所述,可结合基于列的扫描1320使用轻量数据高速缓存,但它不执行聚集。最后,来自基于列的排序1310的结果集被表示为行集1302来返回给客户机。
在这一点上,如所示的,在长RLE序列(例如,性别)上应用过滤将仍返回连续数据ID的组块(c行号)。然而,它们是表示已过滤的连续数据的虚拟组块。由此,对(数据ID,行号,c行号)的排序可以通过使用(数据ID,行号)作为组合键,并跟踪c行号来执行。
还要注意,RLE组块可通过过滤运算被分段为如下形式:
(数据ID1,行号1,c行号1)
(间隙)
(数据ID1,行号2,c行号2)
(间隙)
(数据ID1,行号3,c行号3)
(数据ID2,行号4,c行号4)
(间隙,等等)
由于期望在最终视图中保存存储行的次序,因此可链接对应于同一数据ID的行号,即使它们是有间隙的,并且具有以下形式:
(数据ID1)->(行号1,c行号1),(行号2,c行号2),(行号3,c行号3)
(数据ID2)->(行号4,c行号4)
现在排序要快得多(仅对最终窗口内可见的不同数据ID而非实际行排序)。
一旦已排序,则可在专用于WHERE子句的索引中聚集这些结果,该索引也跟踪移动和,例如行号被保持,但是不再需要c行号因为它可从移动和中被推断出。
由此,该索引的格式可被视为包含(行号,移动和)的表。注意,该索引是专用于WHERE子句的,并且可任选地被高速缓存。如果被高速缓存,则出于压缩原因并且为了使该数据在万一随后对经高速缓存的WHERE应用更有限制的AND子句时被反馈给查询核,可能值得将高速缓存保持为物理存储表。
关于对c行号和“轻量数据高速缓存”的查询核支持,查询核可用于获得用于此处的选择排序的某些统计量(例如,已过滤数据上的GROUPBY),并且查询核用于一旦知道了所涉及的数据ID就获得实际的已过滤行。
但是行本身不被输出,相反,使用帮助执行面向桶的排序算法的(数据ID,行号,c行号)。
关于对采用(数据ID,行号,c行号)的形式来请求行的查询获得行号和c行号,可挂钩返回行号(而非数据ID)的某些虚拟列,并且可通过对每一行计数来实现“轻量数据高速缓存”中的聚集,但是这可能较慢,因为查询核将使用某种虚拟机制来获得行,或者整个假列可被物化,但这会破坏扫描/桶化的纯度,因为每一行将具有不同的行号。另一个“假”(但为纯的)列可能用于对匹配过滤的实际行号(c行号)进行计数。这也将会是较慢的,但在这一情况下,可模拟始终返回Pure()值的轻量枚举器(LightEnumerator)。
一种较快的解决方案将是向查询核添加将(行号,c行号)输出到特殊数据高速缓存中的逻辑。
在这一情况下,查询核内的桶处理器将对每一个桶评估谓词,但是对每一匹配评估WHERE子句一次:
如果WHERE是纯的且用于已排序列的桶是纯的-其需要发送到数据高速缓存
a.已排序列的纯(数据ID)-作为DC坐标
b.桶开始的行号-作为DC坐标
c.桶大小(c行号)-作为聚集的度量
如果WHERE是纯的且用于已排序列的桶是非纯的-或者
如果WHERE是非纯的且用于已排序列的桶是纯的-或者
如果WHERE是非纯的且用于已排序列的桶是非纯的
a.已排序列的当前数据ID-作为DC坐标
b.找到匹配行的行号-作为DC坐标
c.(c行号)-作为聚集的度量
在SKIP+TOP匹配之后停止是任选的,但是在某些情况下(例如,数据未排序但应用了过滤),其中已知一旦过滤接受了SKIP+TOP数量的行(来自一个段),则对于窗口不需要更多数据。对于内部请求,分段查询可被配置成更快地停止且不扫描任何更多数据,因为它无论如何都不会被输出。基于列的扫描可以在那时停止。
关于轻量数据高速缓存,不执行从查询核获得的(数据ID,行号,c行号)数据上的聚集,但它应准备好排序。为此,代替使用标准数据高速缓存,可将专用的“轻量”数据高速缓存挂钩到查询核,该专用“轻量”数据高速缓存不能进行任何真实聚集、但是以将方便排序的形式来累积(数据ID,行号,c行号)。
从查询核的观点,该数据高速缓存(逻辑上)看上去像图14,其具有所表示的单元1400。注意,在离散化的情况下,数据ID将在图14中用组ID来替换。
在现实中,不命中相同的(行号,数据ID)坐标,并且求和是不必要的(可执行对包含相同数据ID的跨段行的某种接合,但是这不同于“标准”求和,因为行号实际上是不同的)。
对于给定的段,已知查询核从最低行号到最高行号顺序地扫描数据,因此行号将按照递增的次序(在段的边界内)。这意味着行号将变得“预”排序。
对于快速排序,基于主排序键=数据ID且次排序键=存储行号,跟踪不同的数据ID,并且还跟踪给定段内的连续(行号,c行号)的序列。
可使用每一段的散列(数据ID)->(行号,c行号)的已排序序列来实现这一点。在(多重合并阶段)的最后,能以O(1)时间整理来自不同段的这些已排序序列,因为如果(段号1<段号2),则段号1中的所有行在段号2中的行之前。
物理上,对于每一段,散列将类似图15,其具有键:指向行号,c行号对所描述的值的数据ID 1500。可使用用于递增策略的递增分配器或基于估计的策略来增长与组块序列相关联的存储器。
对于数据ID或组ID的实际排序,如果应用了离散化,则可在查看实际值之前执行窗口中的不同值的排序(如果使用了按照值的数据ID,如果使用了组ID,或如何分层信息是可用的)。
关于轻量数据高速缓存的合并,可获得来自查询核的多个“轻量”数据高速缓存作为内部请求的结果。这是因为实际上查询聚集器在多个处理器上调度多个分段查询(每一个段一个),并且在结束时,在不同数据高速缓存中可得到最多为处理器数量的分段查询。
在最终阶段期间,能通过利用一个段中的所有行号要么大于要么小于另一段中的所有行号(意味着对于给定数据ID,组块列表的接合将起作用)的性质以O(m)时间快速合并多个散列(其中m=可见窗口中的不同数据ID)。
对于构建最终索引,这基本上是取决于WHERE子句、SORT列和(通常偏态的)数据ID的集合的索引。
从最终查询核结果中,在最一般的情况下获得以下数据:
(数据ID)->(行号,c行号),(行号,c行号),(行号,c行号)...
这在以上步骤中排序,其中获得已排序且随后被多重合并的多个未排序数据高速缓存。然后,获得以下数据:
(已排序数据ID)->(行号,c行号),(行号,c行号),(行号,c行号)...
从中构建索引:
(行号,移动和)
行号是来自查询核的存储行号。
移动和给出了(SKIP,TOP)窗口位于其上的虚拟行号。该索引也可被高速缓存,这可避免重新扫描数据来构建轻量数据高速缓存,并且扫描可能足够快。
关于输出行,查询处理组件代码路径和输出行集的相关的UI组件可使用相同的机制。基于向其添加了(行号,组块号)作为生产者的查询指定(选择了列)所创建的行集以及直接解码的行被输出(从对应的行获得数据ID,并转向字典来用结果填充各行)。ISAM类型的访问因此仅是一种特定访问情况,其中仅添加对于(行号,组块号)的单个(SKIP,TOP)值。
关于执行流程,在一个实现中采取了模块化方法。
图16示出了分析查询指定模块过程流。在开始1600之后,如果在1610指定了排序,则如果尚未高速缓存直方图1640,则在1640计算该直方图。如果高速缓存了直方图,则在1660分析局部窗口分布。如果在1610未指定排序,则在1620确定是否指定了过滤。如果是,则该流程前进到1630。如果否,则在1650确定并输出行集。
图17示出了计算直方图模块过程流。步骤1710确定是否需要离散化。如果是,则在1720确定是否按照值来编码。如果否,则在1730确定分层结构是否可用。如果否,则几乎不能做任何事情且处理可能很慢。如果在1710不需要离散化,则组ID=数据ID,并且该流程继而获得统计量1740,然后在1750基于组ID来对统计量排序并在1760计算移动和。在1770,可任选地高速缓存直方图,并且最后,在1780分析局部窗口分布。类似地,如果如1720处所确定地要按照值来编码,则组ID=数据ID/间隔,并且该流程再次前进到1740。如果进而在1730分层结构是可用的,则组ID=分层结构位置(数据ID)/间隔,并且该流程如上所述再次前进到1740。
图18示出了分析局部窗口分布模块过程流。在1800,标识候选组ID。在1810,标识候选数据ID。然后,在1820,确定是否预期已聚类的数据ID。如果是,则在1840,应用基于列的排序技术。如果否,则在1830,使用标准选择算法1830。
图19示出了标准选择算法模块过程流。在1900,选择候选(数据ID,行号)。在1910,按照组合键对候选排序。在1920,使用直方图计算(SKIP,TOP)窗口。在1930,最终输出行集。在这一点上,这是标准选择算法,其对于预期要返回巨大的窗口的情况是有用的,例如预期其上有极少重复(或连续组块)的数据(例如,平均每一数据ID有低于四个连续重复)上的前一百万以上的行的情况。在这一情况下,跟踪连续组块c行号是不值得的,因为开销超出了获益。
图20示出了VertiSort选择模块过程流,该过程在以下更详细描述。在2000,确定是否高速缓存了索引。如果是,则该流程跳至2060来使用直方图和索引计算(SKIP,TOP)窗口。如果否,则在2010,咨询具有(数据ID,行号,c行号)的轻量数据高速缓存。在2020,将数据ID整理为(行号,c行号)。在2030,对不同数据ID进行排序。在2040,计算索引(行号,移动和)。在2050,可对高速缓存进行索引,然后该流程再次前进到2060来使用直方图和索引计算(SKIP,TOP)窗口。最后,在2070,输出行集结果。
对于输出行集模块,在一个实施例中,基于所指定的行号的所选(可能多个)组块生成XM查询行集(XMQueryRowset),并将该行集作为客户机请求结果的一部分返回给服务器。
关于高速缓存已过滤结果上的直方图和索引,“已排序统计量”描述了什么物理行对应于一个(或任何)所查看的数据的窗口(给定过滤和排序次序)。由此,可履行当前请求,并且丢弃该索引(如果计算上是廉价的话),或者可将该索引高速缓存并在之后重用,例如在用户向下滚动、从升序切换到降序排序次序、添加新的数据列、添加新的AND或甚至OR子句等的时候。
高速缓存是任选的,但是可节省对相同结果的重新计算,并且给出了性能提升,尤其是在关于相同查询的滚动期间。例如,如果可保存已过滤数据上的索引,其保持(行号,移动和)记录,则避免了两个查询核内部请求。
并且,高速缓存在涉及用户向现有WHERE添加更多限制性(AND)子句的情形中可能是有帮助的。在这一情形中,可检索包含(行号,移动和)超集的(非完美)匹配高速缓存索引,并且可向查询核提供来自该数据(置于列存储中)的行号,并且只传递附加的WHERE子句(更快的查询核评估)。
高速缓存的(行号,移动和)索引不必存储任何实际数据ID(即,不指定任何种类的粒度),因此它们可在对涉及选择中的其他列、但具有相同的WHERE子句的查询没有任何额外成本的情况下重复使用。
一旦获得了确切的高速缓存命中,则可通过从高速缓存存储的行号和行计数(例如,通过计算移动和的增量)来生成XM查询行集。可使用各种高速缓存策略,例如,使用用于UI情形的使用模式的专用知识来确定高速缓存内的生存期,使用来自调度器的统计量和临时结构的存储器成本来确定索引的值,使用索引f(CPU成本/存储器使用)的成本值在收回期间确定高速缓存内的生存期,使用索引f(CPU成本/存储器使用)的成本值来确定是否要高速缓存项,等等。
因此,描述了一种通用方法,且在图21中示出。在2110,从应用接收蕴含对数据的过滤和/或排序运算以便检索应用于局部窗口的数据子集的查询。在2120,计算关于查询的任何指定的WHERE子句和/或ORDERBY列的行分布的统计量。在2130,基于统计量,确定与局部窗口匹配的、对所述一个过滤和/或排序运算的结果集。在2140,将结果集发送到应用。
图22示出了从请求客户机的观点来看的流程。在这一点上,在2210,从应用发送蕴含对数据的至少一个过滤和/或排序运算以便检索应用于局部窗口的数据子集的查询。在2220,基于上述基于统计量的分析来返回结果集。在2230,可高速缓存在获得该结果时使用的一个或多个结果或中间结构。
补充上下文参考:基于列的数据编码
如在概览中所提到的,在各实施例中可向大量数据应用面向列的编码和压缩来压缩且同时组织数据以使得稍后对数据的扫描/搜索/查询运算显著更高效。在各实施例中,通过确定加窗数据上的统计量,并在计算与所请求的窗口有关的结果时利用这些统计量,来向蕴含了复杂过滤和/或排序运算的对大量数据的查询的情况应用高效的运算。
在一示例性、非限制实施例中,在将原始数据列化成一组值序列,对每一列有一个值序列(例如,串行化数据列的各字段,例如,所有“姓”串行化为一个序列,或所有“PO订单号”串行化为另一序列,等等)之后,对该数据进行“整数化”以便形成每一列的整数序列,该整数序列根据字典编码、值编码或字典编码和值编码一起以任意次序来统一地表示。该整数化阶段得到统一表示的列向量,并且本身能达到显著的节省,尤其是在数据中记录了诸如文本串等长字段的情况下。接着,检查所有的列,压缩阶段迭代地将行程长度编码应用于任何列的行程,这将导致对整体的列向量集合的最大量的整体大小节省。
如上所述,打包技术是基于列的,其不仅提供了优秀的压缩,而且该压缩技术本身有助于在一旦将压缩的整数列向量递送到客户机侧之后快速地处理数据。
在各非限制实施例中,如图23所示,提供了基于列的编码器/压缩器2310来用于压缩大规模数据存储2300并且还用于使得结果对于数据的扫描/搜索/查询运算显著更高效。响应于数据处理区C中的数据消费设备120的查询,压缩器2310通过数据传输区B的传输网络2315来发送涉及该查询的压缩列。该数据被递送到存储器内存储2330,且因此对相关列的解压可以由数据处理区C中的解码器和查询处理器140来非常快地执行。在这一点上,向涉及该查询的解压的列所表示的行应用桶走查来获得额外的高效处理层。在桶走查期间充分利用行的相似性,使得重复动作被一起执行。如以下更详细描述的,当以具有196Gb RAM的标准或商用服务器将该技术应用于真实的样本数据,如大量的web通信数据或交易数据时,以大约每秒1.5T字节数据实现了服务器数据的查询/扫描,这是超越常规系统的能力的极大飞跃,却只花费了显著降低的硬件成本。
尽管可被压缩的具体数据类型决不限于任何特定数据类型,且取决于对巨大量的数据的大规模扫描的情形数量类似地是无限的,但在实时商业智能应用中将这些技术应用于商业数据或记录的商业重要性是不容置疑的。该压缩技术所实现的查询处理速度的极大获益将实时报告和趋势标识带到了一个全新的水平。
编码器的一个实施例在图24中概括地示出,其中在2400处,从存储接收或读取原始数据,此时编码装置和/或编码软件2450在2410处将数据组织为列。在2420处,将列流变换成统一向量表示。例如,可应用整数编码来将像姓名或地点这样的各个条目映射到整数。这一整数编码可以是字典编码技术,该技术可将数据减小2倍到10倍。另外,或另选地,值编码可在大小上提供1倍到2倍的减小。这在2420处为每一列留下了一整数向量。这一性能提高对所压缩的数据敏感,并且这一大小减小范围仅作为非限制估计来给出,以便给出不同步骤的相对性能的一般概念。
然后,在2430处,可进一步压缩已编码的统一列向量。在一个实施例中,应用行程长度编码技术,该技术确定所有列上的最频繁的值或值的出现,在这一情况下,为该值定义一行程长度,且该过程迭代直到行程长度编码的益处为边际效益的时刻,例如对于在列中具有至少64次出现的重复出现的整数值。
在另一实施例中,检查应用行程长度编码所得的位节省,并且在该迭代过程的每一步,通过应用对行程长度的重新排序和定义来选择各列中达到最大位节省的列。换言之,由于目标是用尽可能少的位来表示列,因此在每一步,在提供最大节省的列处最大化了位节省。就这一点而言,行程长度编码本身可以提供显著的压缩改善,例如100倍或更多。
在另一实施例中,在2430处应用混合压缩技术,该技术采用了位打包和行程长度编码的组合。应用检查两种技术的潜在节省的压缩分析,并且在例如认为行程长度编码导致不足够的净位节省的情况下,则向列向量的其余值应用位打包。因此,一旦根据一个或多个准则确定行程长度节省是最小的,则该算法对于该列的其余相对唯一的值切换到位打包。例如,在列中所表示的值变得相对唯一(其中非独唯一或重复值已经被行程长度编码)的情况下,可对这些值应用位打包而非行程长度编码在2440处,输出的是对应于根据上述技术编码并压缩的列值的一组压缩的列序列。
在一个实施例中,当根据上述技术的压缩列被加载到消费客户机系统上的存储器中时,该数据跨每一列C1、C2、C25、C4、C5、C6来分段,以形成段2500、2502、2504、2506等等,如图25所示。在这一点上,由于每一段可包括数亿行或更多,并行化提高了例如根据查询对数据的处理或扫描速度。每一段的结果被聚集,以形成一组完整的结果,而每一段被分开处理。
图26概括地根据以原始数据2600的输入为开始的流程图描述了上述方法。在2610,如上所述,根据原始数据2600的列来重新组织数据,而不是像常规系统那样将记录的每一字段保持在一起。例如,如图27所示,每一列形成一独立的序列,如序列C2701、C2702、C2703、C2704、C2705、C2706。在零售交易数据是该数据的情况下,例如,列C2701可能是产品价格的串,列C2702可能表示购买日期的串,列C2703可能表示商店位置,等等。考虑到计算机系统所收集的大多数真实世界数据在所表示的值方面并不是非常不同的,因此基于列的组织维持了数据类型内的固有相似性。在2620处,基于列的数据经历一个或多个转换来形成统一表示的基于列的数据序列。在一个实施例中,步骤2620经由字典编码和/或值编码将每一列简化为数据的整数序列。
在2630处,用行程长度编码过程以及可任选地用位打包来压缩基于列的序列。在一个实施例中,行程长度编码过程对所有各列中达到最高压缩节省的列的列数据值序列重新排序。由此,行程长度编码达到最高节省的列被重新排序来对由行程长度编码替换的共同值进行分组,然后为重新排序的组定义行程长度。在一个实施例中,跨各列迭代地应用行程长度编码算法,在每一步检查每一列来确定将达到最高压缩节省的列。
当根据一个或多个准则应用行程长度编码的益处变为边际效益或最小,如不足够的位节省或节省小于一阈值时,则其应用的益处相应地下降。结果,该算法可以停止,或者对于每一列中未被行程长度编码来编码的剩余值,可应用位打包来进一步降低对这些值的存储要求。在组合中,混合行程长度编码和位打包技术可能是强大的,以便减小列序列,尤其是具有序列中表示的有穷或有限数量的值的那些序列。
例如,字段“性别”仅有两个字段值:男和女。采用行程长度编码,这一字段可被相当简单地表示,只要数据是根据如上所述的原始数据的基于列的表示来编码的。这是因为背景中所描述的聚焦于行的常规技术实际上通过将每一记录的字段保存在一起而破坏了列数据的共同性。接在诸如“21”等年龄值后面的“男”不如仅仅接在“男”或“女”值后面的“男”值压缩得那样好。由此,数据的基于列的组织启用了高效的压缩,且该过程的结果是数据2640的一组离散的、统一表示且压缩的、基于列的序列。
图28给出了基于实际数据的列化过程的示例。图28的示例针对4个数据记录2800、2801、2802和2803,但这仅出于图示简单的目的,因为本发明可适用于上万亿字节的数据。一般而言,当计算机系统记录交易数据时,它是逐个记录地记录的,且一般按照接收记录的时间次序来记录。由此,数据实际上具有对应于每一记录的行。
在图28中,记录2800具有带有值“Jon”28zz的姓名字段2810、带有值“555-1212”2821的电话字段2820、带有值“jon@go”2831的电子邮件字段2830、带有值“2 1st St”2841的地址字段2840、以及带有值“Wash”2851的州字段2850。
记录2801具有带有值“Amy”2812的姓名字段2810、带有值“123-4567”2822的电话字段2820、带有值“Amy@wo”2832的电子邮件字段2830、带有值“1 2nd Pl”2842的地址字段2840、以及带有值“Mont”2852的州字段2850。
记录2802具有带有值“Jimmy”2813的姓名字段2810、带有值“765-4321”2823的电话字段2820、带有值“Jim@so”2833的电子邮件字段2830、带有值“9 Fly Rd”2843的地址字段2840、以及带有值“Oreg”2853的州字段2850。
记录2803具有带有值“Kim”2814的姓名字段2810、带有值“987-6543”2824的电话字段2820、带有值“Kim@to”2834的电子邮件字段2830、带有值“91 Y St”2844的地址字段2840、以及带有值“Miss”2854的州字段2850。
当行表示2860被列化为重新组织的列表示2870时,代替具有各自有5个字段的4个记录,形成对应于这些字段的5个列。
由此,列1对应于带有值“Jon”28zz、之后是值“Amy”2812、之后是值“Jimmy”2813、之后是值“Kim”2814的姓名字段2810。类似地,列2对应于带有值“555-1212”2821、之后是值“123-4567”2822、之后是值“765-4321”2823、之后是值“987-6543”2824的电话字段2820。列3对应于带有值“jon@go”2831、之后是值“Amy@wo”2832、之后是值“Jim@so”2833、之后是值“Kim@to”2834的电子邮件字段2830。进而,列4对应于带有值“2 1st St”2841、之后是值“1 2nd Pl”2842、之后是值“9 Fly Rd”2843、之后是值“91 Y St”2844的地址字段2840。以及,列5对应于带有值“Wash”2851、之后是值“Mont”2852、之后是值“Oreg”2853、之后是值“Miss”2854的州字段2850。
图29是示出此处所描述的实施例采用的字典编码的非限制示例的框图。典型的城市列2900可包括值“Seattle”、“Los Angeles”、“Redmond”等等,且这些值可以不断地重复自己。采用字典编码,已编码的列2910包括对应于每一不同值的码元,如每一值一个唯一整数。由此,代替多次表示文本“Seattle”,存储整数“1”,这要紧凑得多。越经常重复自己的值可以用到最紧凑表示(最少位、最少位变化等)的映射来枚举。值“Seattle”仍作为字典2920的一部分被包括在编码中,但是“Seattle”只需被表示一次而非许多次。已编码列2910的存储节省远超过了字典2920所蕴含的额外存储。
图30是示出此处所描述的实施例采用的值编码的非限制示例的框图。列3000表示销售额,且包括典型的包括小数的美元和美分表示,这涉及浮点存储。为了使存储更紧凑,采用值编码来编码的列3010可向其应用因子10,例如102,以便使用整数代替浮点值来表示各值,其中整数需要较少的位来存储。该变换可类似地应用于减少表示值的整数数量。例如,列中始终以百万结束的值,如2,000,000、185,000,000等都可除以106来将值减小到更紧凑的表示2、185等。
图31是示出此处所描述的实施例采用的位打包的非限制示例的框图。列3100表示通过字典和/或值编码来整数化的订单量,但保留了每行32位来表示这些值。位打包试图对段中的值使用最少数量的位。在该示例中,可使用10位/行来表示值590、110、680和320,这表示了对于被应用来形成列3110的第一层位打包的充分节省。
位打包还可移除共同的10(或其他数字)的幂来形成第二打包列3120。由此,如果值如同该示例中那样以0结束,这意味着不需要使用3位/行来表示订单量,且将存储结构减少到7位/行。类似于字典编码,位节省远超过了由于将数据恢复到列3100所需的元数据(如使用10的几次幂)而引起的任何增加的存储。
作为形成第三打包列3130的另一层位打包,可以认识到它采取7位/行来表示像68那样的值,但是由于最低值是11,则范围可位移11(将每一个值减去11),因而最高数是68-11=57,这可以仅用6位/行来表示,因为有26=64个值可能性。尽管图31表示了打包层的特定次序,但各层可用不同的次序来执行,或者另选地,打包层可被选择性地移除或用其他已知的位打包技术来补充。
图32是示出此处所描述的实施例采用的行程长度编码的非限制示例的框图。如图所示,由于值的重复,诸如列3200等表示订单类型的列可用行程长度编码来高效地编码。列值行程表3210将订单类型映射到订单类型的行程长度。尽管表3210的元数据的表示上允许些许变化,但基本思想是行程长度编码对于100的行程长度可给出50倍的压缩,这要优于位打包一般可为同一数据集提供的增益。
图33是此处提供的一实施例的概括框图,其中将各技术合成到统一编码和压缩方案的各实施例中。原始数据3300根据列组织3310被组织为列流。字典编码3320和/或值编码3330提供了如上所述的相应大小减小。然后,在混合RLE和位打包阶段,压缩分析3340在确定是应用行程长度编码3350还是位压缩3360时跨各列检查潜在的位节省。
在图34的流程图中对图33进行扩展。在3400,根据固有行表示来接收原始数据。在3410,将数据重新组织为列。在3420,应用字典和/或值编码来第一次减小数据。在3430,可应用如上所述的混合RLE和位打包技术。在3440,存储基于压缩的且编码的列的数据序列。然后,当客户机请求全部基于压缩的已编码列的数据序列或请求其一子集时,在3450,将受影响的列发送到作出请求的客户机。
图35是执行混合压缩技术的压缩分析的示例性方式的框图。例如,从列3510中计算直方图3500,该直方图表示值的出现频率,或各个行程长度的出现频率。任选地,可设置阈值3512,使得行程长度编码不应用于其中行程长度增益可能最小的、数量上较少的值的重复出现。另选地,或另外地,位节省直方图3520不仅表示了值的出现频率,而且还表示了将通过应用该混合压缩模型的压缩技术中的一种或另一种来达到的总的位节省。另外,再一次可任选地应用阈值3522以便画出其中行程长度编码益处不足以应用该技术的线。取而代之,可对列的这些值应用位打包。
另外,任选地,在应用列3500的行程长度编码之前,可对列3500重新排序来将所有最相似的值分组为经重新排序的列3530。在该示例中,这意味着将A分组在一起以供行程长度编码,并留下B进行位打包,因为对于2个B值,频率和总的位节省都未证明行程长度编码是合理的。在这一点上,可向其他列应用重新排序来保持记录数据处于锁定步骤,或者它可经由关于如何撤消行程长度编码的重新排序的列专用元数据来记住。
图36示出了一相似的示例,其中向相似的列3600应用压缩分析,但是更改了每一次替换行程长度的位节省,使得现在,根据混合压缩分析判断要对2个B值执行行程长度编码(即使是在10个A值之前),因为2个B值导致更高的净位节省。在这一点上,与贪食者从具有不同食物的10个不同盘子中进行选择非常相像,应用行程长度编码是“贪婪的”,这表现在它在每一步都跨所有列寻找大小减小方面的最高增益。类似于图13,可构建频率直方图3610和/或位节省直方图3620数据结构,以便作出关于是应用如所描述的行程长度编码还是位打包的确定。同样,在决定是否采取RLE或位打包时可使用任选阈值3612和3622。经重新排序的列3630可帮助行程长度编码定义更长的行程长度,且因此达到更大的行程长度节省。
图37示出了行程长度编码的“贪婪”方面,该方面在每一步跨所有列来检查哪里达到最高位节省,并且可任选地包括将列重新排序为列3730、3732等来最大化行程长度节省。在某一点,行程长度节省可能相对不重要,因为值是相对唯一的,此时停止行程长度编码。
在混合实施例中,向其余值的范围应用位打包,这在图38中示出。在这一点上,应用混合压缩技术,经重新排序的列3800包括RLE部分3810和位打包部分3820,它们一般分别对应于重复出现的值和相对唯一的值。类似地,经重新排序的列3802包括RLE部分3812和BP部分3822。
在图39所示的一个实施例中,混合算法计算来自位打包的位节省和来自行程长度编码的位节省3900,然后在3910将来自位打包的位节省和来自行程长度的位节省进行比较或检查这两种节省以便在3920确定哪一压缩技术最大化位节省。
上述编码和压缩技术的示例性执行示出了可在真实数据样本4001、4002、4003、4004、4005、4006、4006、4007和4008上达到的显著增益,其范围在大约9倍到99.7倍的性能改进,且特别地取决于特定的大规模数据样本中的相对的值重复量。
图41是示出此处在各实施例中描述的列化、编码和压缩过程的最终结果的框图。在这一点上,每一列C1、C2、C3、...、CN包括具有向其应用行程长度编码的同类重复值的区域,以及图中标记为“其他”的、表示列中的各组异类值的其他区域。具有由行程长度定义的相同的重复值的区域是纯区域4120,且具有多样化值的区域是非纯区域4110,如图例中所指示的。在这一方面,当一个人的眼睛“走查”各列时,作为此处讨论的压缩技术的固有好处,浮现数据上的新视图。
跨所有各列,在非纯区域4110和纯区域4120之间或从相反方向的第一转换点,按照从第一行到转换点处的行的各行来定义桶。在这方面,桶4100沿着各列向下在每一转换点处定义,如虚线所示。桶4100由各转换之间的行来定义。
图42示出了基于跨特定行的纯和非纯区域的数量来为桶定义的命名法。纯桶4200是没有非纯区域的桶2000。单非纯桶4210是跨该桶的各行具有1个非纯区域的桶。双非纯桶4210是跨该桶的各行具有2个非纯区域的桶。三非纯桶具有3个非纯区域,以此类推。
由此,在示例性数据加载过程期间,以适合稍后的高效查询的表示来对数据进行编码、压缩、存储,并且压缩技术可以是所使用的查找一段内的数据分布并试图比位打包更频繁地使用RLE压缩的技术。在这一点上,RLE对于压缩和查询都提供了以下优点:(A)RLE通常比位打包需要少得多的存储,以及(B)RLE包括高效地“快进”通过数据范围同时执行诸如“按......分组”、“过滤”和/或“聚集”等查询构件块运算的能力;这些运算可以在数学上变成对按列组织的数据的高效运算。
在各非限制实施例中,代替在对同一段中的另一列进行排序之前一次对一个列进行排序,该压缩技术基于数据的分布来对数据行进行聚类,且由此增加了在段中对RLE的使用。如此处所使用的,术语“桶”用于描述行的聚类,为了避免疑惑,该术语应被认为与术语“分区”不同,分区是定义明确的在线分析处理(OLAP)和RDBMS概念。
以上讨论的技术由于认识到数据分布是歪斜的且在大量数据中很少存在均匀分布,因而是有效的。在压缩用语中,算术编码通过以下来充分利用这一点:以总计使用较少的位为目的,使用较少的位来表示频繁使用的字符,并使用较多的位来表示不频繁使用的字符。
采用位打包,利用固定大小的数据表示来进行较快的随机存取。然而,此处描述的压缩技术还具有使用RLE的能力,这提供了对于较频繁的值使用较少的位的方式。例如,如果原始表(为图示简明起见,包括一个列“Col1”)表现如下:
Col1
100
100
100
100
200
300
400
则在压缩之后,Col1表现如下,其被划分成应用行程长度编码的第一部分和应用位打包的第二部分:
如从以上可见,最常见的值100的出现被折叠成RLE,而较不频繁出现的值仍以固定宽度的、经位打包的存储来存储。
在这一点上,上述数据打包的实施例包括两个不同阶段:(1)数据分析,用于确定桶化,以及(2)段数据的识别,用于遵守桶化布局。这两个阶段中的每一个在以下示例性地详述。
关于确定桶化的数据分析,目标是用RLE来覆盖段内尽可能多的数据。由此,该过程朝向偏向“较厚”列,即具有大基数的列来偏斜,而不是将在查询期间被更频繁使用的列。也可应用基于使用的优化。
对于另一简单示例,出于图示的目的,使用以下的小表。实际上,此类小表一般不被包括在上述压缩的范围内,因为对此类表的压缩的好处往往并非有价值的。并且,此类小表一般不被包括是因为在执行编码之后发生压缩,并且在一个实施例中压缩对数据标识(ID)而非值本身起作用。由此,为了图示,还添加了行号列。
在各列上,桶化过程通过找到在段数据中占据最多空间的单个值来开始。如上关于图18和19所提到的,这可例如如下对每一列使用简单直方图统计来完成。
列 最常见的值 出现次数 节省的空间
Col1 100 5 45位
Col2 1231 3 33位
一旦选择了该值,对段中的行进行逻辑重排序,使得该值的所有出现按顺序出现,以便最大化RLE行程的长度:
在一个实施例中,在每一列段中,属于同一行的所有值存在于同一索引处,例如,col1[3]和col2[3]都属于第三行。确保这一点提供了对同一行中的值的高效的随机存取,而不会导致通过用于每一次存取的映射表的间接性的成本。因此,在对贪婪RLE算法或混合RLE和位打包算法的应用的当前描述的实施例中,当对一列中的值重新排序时,这意味着其他列段中的值也被重新排序。
在以上示例中,现在存在两个桶:{1,2,4,6,7}和{3,5}。如所提到的,此处所应用的RLE是贪婪算法,这意味着该算法遵循以找到全局最优为期望来在每一阶段作出局部最优选择的问题解决元启发(metaheuristic)。在找到最大桶的第一阶段之后,下一阶段是选择次大桶,并且在该桶内重复该过程。
现在,当相应地对行重排序时,有三个桶:{2,7}、{1,4,6}、{3,5}。最大桶是第二个,但是那里没有重复值。第一个桶所有列具有RLE行程,并且其余值是唯一的,因此知道在Col1中不会得到进一步的RLE增益。考虑{3,5}桶,有可被转换到RLE的另一值1231。有趣的是,1231也出现在前一桶上,并且该桶可被重新排序,使得1231在底部,并准备好与下一桶的顶部合并。下一步得到以下结果:
在以上示例中,现在存在四个桶:{2,7}、{6,4}、{1}、{3,5}。当无法进一步减少更多数据时,该过程移至段数据重组织的下一阶段。
尽管最上面的图示也对行重新排序,但出于性能原因,对桶的确定可以纯粹基于来自对每一列段中的数据重排序的动作的统计。对每一列段中的数据重排序的动作可以基于可用核使用作业调度器来并行化。
如所提到的,对上述技术的使用对于小数据集是不实用的。对于顾客数据集,上述技术频繁地经历数万步骤,这可能会耗时。由于该算法的贪婪本质,绝大部分的空间节省发生在前几步中。在前几千步中,会被节省的大多数空间已经被节省了。然而,如在压缩的数据的扫描侧上观察到的那样,打包的列中的RLE的存在在查询期间给出了显著的性能提升,因为在查询期间即使是微小的压缩增益也会收获报偿。
由于一次处理一个段,因此可使用多个核,从而将从数据源中将数据读入段中所花费的时间与压缩前一段所花费的时间重叠。采用常规技术,以约100K行/秒的速率从关系型数据库中读取,8M行的段将花费约80秒,这是可供这一工作使用的相当大量的时间。任选地,在一个实施例中,对前一段的打包也可在一旦用于下一段的数据可用时就停止。
基于列的数据编码的处理
如所提到的,根据基于列的编码的各实施例的组织数据的方式有助于在数据的消费侧的高效扫描,其中处理可以在存储器中在选定数量的列上非常快地执行。上述数据打包和压缩技术在行编码期间更新压缩阶段,而扫描包括查询优化器和处理器来充分利用智能编码。
该扫描或查询机制可用于高效地向商业智能(BI)查询返回结果,并且是针对由上述数据打包和压缩技术产生的聚类布局而设计的,且被优化来得到增加的RLE使用,例如,期望在查询处理期间,将使用RLE来压缩大量的用于查询的列。另外,该快速扫描过程引入了面向列的查询引擎,而非在列存储上的行级查询处理器。由此,即使是在包含位打包数据(不是RLE数据)的桶中,由于数据局部性而获得的性能增益也可能是显著的。
除了引入上述数据打包和压缩技术以及高效扫描之外,能以高度有效的方式来支持:查询中的“或”片(slice)以及已经指定了关系的多个表之间的“联接”(Join)。
如以上所提到的,该扫描机制采用了段包含包含跨段的桶,并且在“纯”RLE行程或“非纯”的其他位打包存储中包含列值。
在一个实施例中,在段上调用扫描,关键是一次对一个桶工作。在桶内,取决于查询规范,扫描过程在各阶段内执行面向列的处理。第一阶段是收集关于什么列区域是纯的以及什么区域是非纯的统计信息。接着,可以处理过滤,之后处理分组操作,之后处理代理列。接着,可处理聚集作为另一阶段。
如早先所提到的,注意到此处呈现的用于扫描的各实施例实现了面向列的查询处理,而非像常规系统那样是面向行的。由此,对于这些阶段的每一个,所执行的实际代码可以特定于:(1)所操作的列是否是行程长度编码的,(2)用于位打包的压缩类型,(3)结果是稀疏还是致密的,等等。对于聚集,考虑另外的因素:(1)编码类型(散列或值),(2)聚集函数(求和/最小/最大/计数),等等。
一般而言,扫描过程因而遵循图43的形式,其中来自各种标准查询/扫描运算符4300的查询结果是所有桶行的函数。查询/扫描运算符4300实际可以在数学上进行分解,使得过滤、分组、代理列和聚集在各阶段中彼此分开地处理。
在这一点上,对于每一处理步骤,根据桶走查过程,在4310处,根据桶的不同纯度来处理运算符。因此,代替对所有桶行的一般化的且昂贵的扫描,采用此处描述的编码和压缩算法的工作引入的不同桶的专门化,结果因而是纯桶、单非纯桶、双非纯桶等等的处理的聚集结果。
图41示出了桶的示例分布以及该压缩体系结构的能力,因为对纯桶执行的处理由于处理数学缩减到简单运算而是最快的,之后的第二快的是单非纯桶,且对于其他的非纯桶以此类推。此外,已经发现数量大得令人惊奇的桶是纯的。例如,如图46所示,对于查询所蕴含的六个列,如果每一列具有大约90%的纯度(意味着90%的值由于相似数据而用行程长度编码来表示),则大约60%的桶是纯的,大约1/3将是单非纯桶,大约8%将是双非纯桶,且其余将总计仅有1%。由于对纯桶的处理是最快的,且对单非纯桶和双非纯桶的处理仍然是相当快的,因此具有3个或更多非纯区域的桶的“更复杂”处理被保持在最小。
图45描绘了具有某些样本标准查询构件块的样本查询4500,这些标准查询构件块例如样本“按列过滤”查询构件块4502、样本“按列分组”查询构件块4504、以及样本“按列聚集”查询构件块4506。
图46是示出通过列选择性而产生的带宽减少的另一方面的框图。回顾样本查询4600,可以看到涉及所有列4610中不超过6个列4620,且因此只需要将6个列加载到本地RAM中来获得高效的查询。
因此此处已描述了各实施例。图47示出了用于编码数据的一个实施例,包括在4700处根据对应于该数据的不同数据字段的一组基于列的值序列来组织该数据。然后,在4710,根据诸如字典编码和/或值编码等至少一个编码算法将该组基于列的值序列变换成一组基于列的整数序列。然后,在4720,根据至少一个压缩算法来压缩该组基于列的整数序列,压缩算法包括跨该组基于列的整数序列应用的贪婪行程长度编码算法、或位打包算法、或行程长度编码和位打包的组合。
在一个实施例中,分析该整数序列来确定是应用行程长度编码(RLE)压缩还是位打包压缩,包括分析RLE压缩相对于位打包压缩的位节省来确定何处达到最大位节省。该过程可包括生成直方图来协助确定何处达到最大位节省。
在另一实施例中,如图48所示,位打包技术包括在4800处接收表示数据列的整数值序列的各部分,以及位打包的潜在缩减的三个阶段。在4810,可基于表示数据字段所需的位数来缩减数据。在4820,可通过跨该整数序列的各部分的值移除任何共享的数字幂来缩减数据。在4830,也可通过跨一范围偏移整数序列的各部分的值来缩减数据。
在另一实施例中,如图49的流程图所示,响应于查询,在4900,检索数据的子集作为对应于数据的不同列的整数编码的且压缩的值序列。然后,在4910,基于出现在数据子集的整数编码的且压缩的值序列的任一个中的压缩类型的变化来定义跨数据子集的处理桶。接着,在4920,基于为了得到高效查询处理而处理的当前桶的类型来执行查询运算。这些运算可以在存储器内执行,并且在多核体系结构中并行化。
不同的桶包括:(1)跨各序列桶中不同部分的值都是根据行程长度编码压缩来压缩的,从而定义了纯桶,(2)除了一个部分之外都是根据行程长度编码来压缩的,从而定义了单非纯桶,或(3)除了两个部分之外都是根据行程长度编码来压缩的,从而定义了双非纯桶。
改进的扫描允许更高效地执行各种标准查询和扫描运算符,尤其是对于最纯的桶。例如,当应用桶走查技术且基于桶类型来执行处理时,逻辑“或”查询片运算、已指定了关系的多个表之间的查询联接运算、过滤运算、分组运算、代理列运算或聚集运算都可以更高效地执行。
示例性联网和分布式环境
本领域普通技术人员可以理解,此处所描述的基于列的编码和查询处理的各实施例可以结合任何计算机或其它客户机或服务器设备来实现,该任何计算机或其它客户机或服务器设备可作为计算机网络的一部分来部署或者被部署在分布式计算环境中,并且可以连接到任何种类的数据存储。就此,此处所描述的各实施例可以在具有任意数量的存储器或存储单元以及出现在任意数量的存储单元上的任意数量的应用程序和进程的任何计算机系统和环境中实现。这包括但不限于具有部署在具有远程或本地存储的网络环境或分布式计算环境中的服务器计算机和客户计算机的环境。
分布式计算通过计算设备和系统之间的通信交换提供了计算机资源和服务的共享。这些资源和服务包括信息的交换、对于诸如文件等对象的高速缓存存储和盘存储。这些资源和服务还包括多个处理单元之间的处理能力共享以便进行负载平衡、资源扩展、处理专门化,等等。分布式计算利用网络连接,从而允许客户机利用它们的集体力量来使整个企业受益。在这一点上,各种设备可具有应用、对象或资源,它们可以协作来执行本发明的各实施例中的任一个的一个或多个方面。
附图50提供了示例性的联网或分布式计算环境的示意图。该分布式计算环境包括计算对象5010、5012等以及计算对象或设备5020、5022、5024、5026、5028等,这些计算对象或设备可包括如由应用程序5030、5032、5034、5036、5038表示的程序、方法、数据存储、可编程逻辑等。可以理解,对象5010、5012等以及计算对象或设备5020、5022、5024、5026、5028等可包括不同的设备,诸如PDA、音频/视频设备、移动电话、MP3播放器、个人计算机、膝上型计算机等。
每一个对象5010、5012等以及计算对象或设备5020、5022、5024、5026、5028等可通过通信网络5024直接或间接与一个或多个其他对象5010、5012等以及计算对象或设备5020、5022、5026、5028、5040等进行通信。即使在附图50中被示为单个元件,但网络5040可包括向附图50的系统提供服务的其他计算对象或解释设备,和/或可表示未示出的多个互连网络。每一个对象5010、5012等或5020、5022、5024、5026、5028等还可包含诸如应用5030、5032、5034、5036、5038等应用,应用可利用API或适用于与根据本发明的各实施例来提供的基于列的编码和查询处理进行通信或适用于该基于列的编码和查询处理的实现的其他对象、软件、固件和/或硬件。
存在支持分布式计算环境的各种系统、组件和网络配置。例如,计算系统可以由有线或无线系统、本地网络或广泛分布的网络连接在一起。当前,许多网络被耦合至因特网,后者为广泛分布的计算提供了基础结构并包含许多不同的网络,但任何网络基础结构可用于变得与如各实施例中所描述的基于列的编码和查询处理相关联的示例性通信。
因此,可以利用诸如客户机/服务器、对等、或混合体系结构等网络拓扑结构和网络基础结构的主机。“客户机”是使用与它无关的另一类或组的服务的一个类或组中的成员。客户机可以是进程,即大致上是请求由另一程序或进程提供的服务的一组指令或任务。客户机进程利用所请求的服务,而不必知道摄有关其他程序或服务本身的任何工作细节。
在客户机/服务器体系结构中,尤其在联网系统中,客户机通常是访问由例如服务器等另一计算机提供的共享的网络资源的计算机。在图50的图示中,作为非限制性示例,计算机5020、5022、5024、5026、5028等可被认为是客户机而计算机5010、5012等可被认为是服务器,其中服务器5010、5012等提供数据服务,诸如从客户机计算机5020、5022、5024、5026、5028等接收数据、存储数据、处理数据、向客户机计算机5020、5022、5024、5026、5028发送数据等,但任何计算机都可取决于环境而被认为是客户机、服务器或两者。这些计算设备中的任一个可以处理数据、编码数据、查询数据、或请求可蕴含如此处对于一个或多个实施例描述的基于列的编码和查询处理的服务或任务。
服务器通常是可通过诸如因特网或无线网络基础架构等远程网络或本地网络访问的远程计算机系统。客户机进程可以在第一计算机系统中活动,而服务器进程可以在第二计算机系统中活动,它们通过通信介质彼此通信,从而提供分布式功能并允许多个客户机利用服务器的信息收集能力。按照基于列的编码和查询处理来利用的任何软件对象可以被单独提供或分布在多个计算设备或对象上。
在其中通信网络/总线5040是因特网的网络环境中,服务器5010、5012等可以是客户机5020、5022、5024、5026、5028等通过诸如超文本传输协议(HTTP)等多种已知协议中的任一种与其通信的web服务器。服务器5010、5012等也可担当客户机5020、5022、5024、5026、5028等,这是分布式计算环境的特性。
示例性计算设备
如上所述,有利的是,此处所描述的技术可适用于其中期望快速查询大量数据的任何设备。从而,应当理解,构想了所有种类的手持式、便携式和其他计算设备和计算对象来用于各实施例,即,在设备可能期望扫描或处理巨大量的数据来得到快速且高效的结果的任何地方。因此,以下在附图34中描述的通用远程计算机只是计算设备的一个示例。
尽管并非所需,但各实施例可以部分地经由操作系统来实现,以供设备或对象的服务开发者使用,和/或被包括在用于执行此处所描述的各实施例的一个或多个功能方面的应用软件中。软件可以在由诸如客户机工作站、服务器或其它设备等一个或多个计算机执行的诸如程序模块等计算机可执行指令的通用上下文中描述。本领域的技术人员可以理解,计算机系统具有可用于传递数据的各种配置和协议,并因此没有特定配置或协议应被认为是限制性的。
因此,图51示出了其中可实现各实施例的一个或多个方面的合适的计算系统环境5100的一个示例,尽管如上所述,计算系统环境5100仅为合适的计算环境的一个示例,并非对使用范围或功能提出任何限制。也不应该将计算环境5100解释为对示例性操作环境5100中示出的任一组件或其组合有任何依赖性或要求。
参考附图51,用于实现一个或多个实施例的示例性远程设备包括计算机5110形式的通用计算设备。计算机5110的各组件可包括但不限于,处理单元5120、系统存储器5130、以及将包括系统存储器在内的各系统组件耦合到处理单元5122的系统总线5120。
计算机5110通常包括各种计算机可读介质,并可以是可由计算机5110访问的任何可用介质。系统存储器5130可以包括诸如只读存储器(ROM)和/或随机存取存储器(RAM)等易失性和/或非易失性存储器形式的计算机存储介质。作为示例而非限制,存储器5130还可以包括操作系统、应用程序、其他程序模块、和程序数据。
用户可以通过输入设备5140向计算机5110输入命令和信息。监视器或其他类型的显示设备也经由接口,诸如输出接口5150连接至系统总线5122。除监视器之外,计算机还可以包括其他外围输出设备,如扬声器和打印机,它们可以通过输出接口5150连接。
计算机5110可使用至一个或多个远程计算机,诸如远程计算机5170的逻辑连接在网络化或分布式环境中操作。远程计算机5170可以是个人计算机、服务器、路由器、网络PC、对等设备或其他常见网络节点、或任何其他远程媒体消费或传输设备,并且可以包括上面关于计算机5110所描述的任何或全部元件。附图51所示的逻辑连接包括诸如局域网(LAN)或广域网(WAN)等的网络5172,但也可以包括其他网络/总线。这样的联网环境在家庭、办公室、企业范围计算机网络、内联网和因特网中是常见的。
如上所述,尽管结合各种计算设备和网络体系结构描述了各示例性实施例,但基本概念可被应用于其中需要压缩大规模数据或在大规模数据上处理查询的任何网络系统和任何计算设备或系统。
而且,存在实现相同或相似功能的多种方法,例如适当的API、工具箱、驱动程序代码、操作系统、控件、独立或可下载软件对象等,它们使得应用和服务能够使用该高效的编码和查询技术。由此,此处的各实施例从API(或其他软件对象)的观点以及从提供基于列的编码和/或查询处理的软件或硬件对象构想。因此,此处描述的各实施例可以具有完全采用硬件、部分采用硬件并且部分采用软件、以及采用软件的方面。
在本文中使用的词语“示例性”意味着用作示例、范例或说明。为避免疑惑,本文公开的主题不受限于这样的示例。此外,本文描述为“示例性”的任何方面或设计不必解释成优于其他方面或设计或比其他方面或设计有利,它也不旨在排除本领域的普通技术人员所知的等效示例性结构和技术。而且,就术语“包括”、“具有”、“包含”和其他类似的词语在详细描述或权利要求书中的使用而言,为避免疑惑,这样的术语旨在以类似于术语包括摂作为开放的过渡词的方式解释而不排除任何附加或其他元素。
如上所述,此处所述的各种技术可结合硬件或软件,或在适当时以两者的组合来实现。如在此所使用的,术语“组件”、“系统”等同样指的是计算机相关实体,或者是硬件、硬件和软件的组合、软件或执行中的软件。例如,组件可以是,但不限于是,在处理器上运行的进程、处理器、对象、可执行码、执行的线程、程序和/或计算机。作为说明,运行在计算机上的应用程序和计算机本身都可以是计算机组件。一个或多个组件可以驻留在进程和/或执行的线程中,并且组件可以位于一个计算机内和/或分布在两个或更多计算机之间。
已经关于若干组件之间的交互描述了前述系统。应该理解,这样的系统和组件可以包括根据前述的各种置换和组合的那些组件或指定的子组件、指定的组件或子组件中的某一些、和/或另外的组件。子组件也可以被实现为通信耦合至其他组件而非被包括在父组件(分层)内的组件。另外,应注意到一个或多个组件可被组合成提供聚集功能的单个组件,或被分成若干单独的子组件,且诸如管理层等任何一个或多个中间层可被设置成通信耦合到这样的子组件以便提供集成功能。此处描述的任何组件也可以与在此未具体描述但本领域的技术人员公知的一个或多个其他组件交互。
考虑到以上描述的示例性系统,参考各附图的流程图将可以更好地理解依照所描述的主题实现的方法。尽管为了简洁起见,作为一系列框示出和描述了方法,但是,应该理解,所要求保护的主题不仅限于所描述的框的顺序,一些框可以按与此处所描绘和描述的不同的顺序进行和/或与其他框并发地进行。尽管经由流程图示出了非顺序或分支的流程,但可以理解,可实现达成相同或类似结果的各种其他分支、流程路径和框次序。此外,并非所有的所示出的方框都是实现下面所描述的方法所必需的。
除了此处所描述的各实施例之外,可以理解,可以使用其他相似的实施例或者可对所述实施例作出修改和添加以便执行对应的实施例的相同或等效的功能而不背离这些实施例。此外,多个处理芯片或多个设备可共享此处所描述的一个或多个功能的执行,并且类似地,存储可以跨多个设备实现。因此,本发明不应限于任何单个实施例,而是应该根据所附权利要求书的广度和范围来解释。