用于半结构化数据的可扩展分析平台的制作方法

文档序号:16838842发布日期:2019-02-12 21:20阅读:418来源:国知局
本公开要求2014年3月14日提交的美国专利申请号14/213,941的优先权,并且还要求2013年3月15日提交的美国临时申请号61/800,432的权益。以上提及的申请的全部公开内容以引用方式并入本文。
技术领域
:本公开涉及一种可扩展交互式数据库平台,并且更具体地说,涉及一种并入有存储和计算的用于半结构化数据的可扩展交互式数据库平台。
背景技术
::本文中所提供的背景描述是出于概括地呈现本公开的上下文的目的。目前所提及的发明人的作品(就本背景部分中所描述的内容来说)以及在提交时可能尚未取得现有技术资格的背景描述的方面既不明确地也不隐含地被认为是针对本公开的现有技术。传统的数据库系统以与基础存储后端紧密集成的查询执行引擎为特点,所述基础存储后端通常是由不具有计算能力的可成块寻址的持久存储装置组成。这些装置(硬盘驱动器和/或固态驱动器)的特征在于(a)根据顺序地还是随机地存取数据而显著不同的存取时间、(b)以块粒度设定的具有固定最小大小的存取单元以及(c)显著比主存储器慢(几个数量级)的存取时间。从存储管理到查询执行到查询优化,这些特性连同存储后端不具有任何非平凡计算能力的假设已对数据库系统的设计具有重要影响。数据库最初充当管理商家日常活动的操作存储区。随着数据库技术在性能和成本两方面的改进,商家认识到需要保持越来越多量的操作历史和商业状态以供稍后分析。此类分析帮助商家洞察其过程并对它们进行优化,进而提供竞争优势和越来越多的利润。数据仓库由于这种需要而产生。商业数据通常被很好地结构化,从而容易填入关系表格中。数据仓库实质上是供应结构化查询语言(SQL)来对这种商业数据进行离线分析的可扩展关系数据库系统,并且针对主读工作负荷进行优化。举例来说,数据仓库包括如Teradata的传统系统以及诸如Vertica、Greenplum和AsterData的较新供应商。他们提供SQL接口、索引和快速列式访问。通常,周期性地(例如,每夜或每周)向数据仓库加载从各种源和操作系统摄取的数据。对这种数据进行清理、策划并统一成单个模式并且将其加载到仓库中的过程被称为提取-变换-加载(ETL)。随着源和数据的种类增加,ETL过程的复杂性也增加。成功地实施ETL(包括定义恰当的模式并且将输入数据匹配到预定模式)可能需要专业人员花费数周到数月,并且可能很难或不可能实施改变。市场上有很多工具(诸如Abinitio、Informatica和Pentaho)来辅助ETL过程。然而,ETL过程大体上仍是麻烦的、脆弱的且昂贵的。数据分析市场已经爆发出使得商业用户易于对仓库中的数据执行特设(adhoc)迭代分析的许多商业智能和可视化工具。商业智能工具构建仓库数据的多维聚合并且允许用户导航通过并查看这种数据的各种片段和投影。举例来说,商业用户可能想要通过产品种类、地区和商店查看总月度销售。然后,他们可能想要针对特定种类深挖到每周销售或者上升到查看整个国家的销售。多维聚合还可称为在线分析处理(OLAP)立方体。诸如BusinessObjects和Cognos的许多商业智能(BI)工具实现此类分析,并且支持用于查询立方体的称为多维表达式(MDX)的语言。还有诸如MicroStrategy、Tableau和Spotfire的许多可视化工具,其允许商业用户直观地浏览这些立方体和数据仓库。最近,商家想要分析的数据类型已经改变。随着传统实体商业放到网上并且形成新的在线商业,这些商家需要分析领先的公司诸如Google和Yahoo所充斥着的数据类型。这些数据类型包括诸如网页、页面浏览量日志、点击流、RSS(丰富站点摘要)馈入、应用日志、应用服务器日志、系统日志、事务日志、传感器数据、社交网络馈入、新闻馈入和博客贴子的数据类型。这些半结构化数据不能很好地适合传统仓库。它们具有某种固有结构,但结构可能是不一致的。结构可随着时间迅速地改变,并且可随不同源而变化。它们并不是自然列成表格的,并且用户想要对这些数据执行的分析-群集、分类、预测等-不容易用SQL来表达。用于有效利用这些数据的现有工具是麻烦并且不足的。因此,出现了新的高度可扩展的存储和分析平台Hadoop,其由在Google处实施以用于管理web爬行和搜索的技术激发。就其核心来说,Hadoop供应用于可靠地存储其数据的群集式文件系统HDFS(Hadoop分布式文件系统)以及基本的并行分析引擎MapReduce以支持较复杂的分析。从这些部分开始,Hadoop生态系统已经发展成包括带索引的操作存储区HBase和新的查询接口Pig和Hive,它们依赖于MapReduce。Hive是在Hadoop之上添加查询层的Apache项目,其没有在传统仓库中找到的用于查询优化、高速缓存和索引的任何优化。替代地,Hive简单地将类SQL语言(称为Hive-QL)的查询转换为针对Hadoop群集运行的MapReduce工作。传统的商业用户对于Hive有三个主要问题。Hive不支持标准的SQL,并且不具有动态模式。另外,Hive不够快速来允许交互式查询,因为每个Hive查询需要重新解析所有源数据的MapReduce工作,并且通常需要多次通过源数据。Impala是Cloudera的Hadoop实施的用于Hive-QL查询的实时引擎。它对Hive的顺序文件提供分析,并且可最终支持嵌套模型。然而,它不具有动态模式,而是需要用户仍提前针对待查询的数据提供模式。Pig是另一个Apache项目并且提供用于在Hadoop中处理日志文件的无模式脚本语言。如同Hive,Pig将每件事转换成映射-化简工作。同样,其不利用任何索引,并且不够快速来进行交互。Jaql是用于分析JavaScript对象表示法(JSON)日志的无模式声明性语言(与声明性语言如SQL相反)。如同Pig,其编译成Hadoop上的映射-化简程序,并且共有许多相同缺点,包括非交互性速度。Hadoop本身正在相当迅速地流行起来,并且在云中现成可用。Amazon提供弹性的映射-化简,其可实际上等效于在云中运行的Hadoop的MapReduce实施。它对存储于Amazon的基于云的S3(简单存储服务)中的数据起作用,并且向S3输出结果。Hadoop生态系统的优点有三项。第一,系统扩展到极限大小并且能够存储任何数据类型。第二,与传统仓库相比,它具有极低成本(便宜多达20倍)。第三,它是开放源,这避免了与单个供应商锁定。用户想要针对恰当工作挑选恰当工具的能力,并且避免在系统之间移动数据来完成其工作。虽然Hadoop较灵活,但使用Hadoop需要具有深厚知识的专门技术管理员和程序员,通常很难找到这些人员。此外,Hadoop太慢而不具交互性。即使最简单的查询也需要数分钟到数小时来执行。Dremmel是在Google处内部开发的工具,其对嵌套关系或半结构化数据提供基于SQL的分析查询。原始版本处理呈ProtoBuf格式的数据。Dremmel需要用户提前针对所有记录定义模式。BigQuery是Dremmel的基于云的商业化,并且扩展到处理CSV和JSON格式。Drill是Dremmel的开放源版本。Asterix是用于使用抽象数据模型(ADM)和注释查询语言(AQL)管理和分析半结构化数据的系统,所述ADM是JSON的普遍化。Asterix不支持标准SQL,也没有本公开所给予的快速访问。技术实现要素:一种数据变换系统包括模式推断模块和导出模块。模式推断模块被配置用于动态地创建用于从第一数据源检索到的对象的累积模式。检索到的对象中的每一个包括(i)数据和(ii)描述所述数据的元数据。动态地创建累积模式包括:针对检索到的对象中的每个对象,(i)从所述对象推断模式以及(ii)选择性地更新累积模式以便根据所述推断出的模式来描述所述对象。导出模块被配置用于根据所述累积模式将检索到的对象的数据输出到数据目的地系统。在其他特征中,数据目的地系统包括数据仓库。在其他特征中,数据仓库存储关系数据。在其他特征中,导出模块被配置用于将累积模式转换成关系模式并且根据关系模式将检索到的对象的数据输出到数据仓库。在其他特征中,导出模块被配置用于产生用于数据仓库的命令,所述命令更新数据仓库的模式以反映对关系模式做出的任何改变。在其他特征中,导出模块被配置用于根据关系模式从检索到的对象的数据创建至少一个中间文件。在其他特征中,至少一个中间文件具有预定义的数据仓库格式。在其他特征中,导出模块被配置用于将所述至少一个中间文件批量加载到数据仓库中。在其他特征中,索引存储区被配置用于以列式形式存储来自检索到的对象的数据。在其他特征中,导出模块被配置用于从索引存储区中的存储数据生成基于行的数据。在其他特征中,模式推断模块被配置用于在索引存储区中创建时间索引,所述时间索引将时间值映射到检索到的对象的标识符。在其他特征中,针对检索到的对象中的每个检索到的对象,时间值指示(i)对应于检索到的对象的创建的事务时间或(ii)对应于检索到的对象的有效时间中的至少一个。在其他特征中,写入优化存储区被配置用于(i)高速缓存用于稍后存储在索引存储区中的附加对象并且(ii)响应于高速缓存的大小达到阈值,将附加对象封装在一起用于批量加载到索引存储区中。在其他特征中,模式推断模块被配置用于收集关于检索到的对象的元数据的统计信息。在其他特征中,模式推断模块被配置用于收集关于检索到的对象的数据类型的统计信息。在其他特征中,模式推断模块被配置用于响应于关于数据类型的统计信息,改写检索到的对象中的一些的数据。在其他特征中,模式推断模块被配置用于响应于关于数据类型的统计信息,将检索到的对象中的一些的数据如可能未正确定类型来报告给用户。在其他特征中,模式推断模块被配置用于收集关于检索到的对象的数据的统计信息。在其他特征中,统计信息包括最小值、最大值、平均值和标准偏差中的至少一个。在其他特征中,数据收集器模块被配置用于接收来自第一数据源的关系数据并且生成供模式推断模块使用的对象。在其他特征中,数据收集器模块被配置用于通过创建(i)指示从其中检索到关系数据中的每个项目的表格的第一列以及(ii)指示与关系数据中的每个项目相关联的时间戳的第二列来使关系数据事件化(eventize)。在其他特征中,调度模块被配置用于根据预定的依赖信息将处理工作指派给模式推断模块和导出模块。在其他特征中,导出模块被配置用于将累积模式分区成多个表格。在其他特征中,多个表格中的每一个包括在检索到的对象中一起出现的列。在其他特征中,导出模块被配置用于根据对应于检索到的对象的群组的列来分区累积模式,所述群组具有用于标识符元素的不同值。在其他特征中,模式推断模块记录用于检索到的对象中的每一个的源标识符。在其他特征中,对于检索到的对象中的每个对象,源标识符包括第一数据源的唯一标识符和对象在第一数据源内的位置。一种操作数据变换系统的方法包括动态地创建用于从第一数据源中检索到的对象的累积模式。检索到的对象中的每一个包括(i)数据和(ii)描述所述数据的元数据。动态地创建累积模式包括:针对检索到的对象中的每个对象,(i)从对象推断出模式以及(ii)选择性地更新累积模式以便根据推断出的模式来描述对象。所述方法还包括根据累积模式将检索到的对象的数据输出到数据目的地系统。在其他特征中,数据目的地系统包括数据仓库。在其他特征中,数据仓库存储关系数据。所述方法还包括将累积模式转换成关系模式以及根据关系模式将检索到的对象的数据输出到数据仓库。所述方法还包括产生用于数据仓库的命令,所述命令更新数据仓库的模式以反映对关系模式做出的任何改变。所述方法还包括根据关系模式从检索到的对象的数据创建至少一个中间文件。在其他特征中,至少一个中间文件具有预定义的数据仓库格式。所述方法还包括将至少一个中间文件批量加载到数据仓库中。所述方法还包括将来自检索到的对象的数据以列式形式存储在索引存储区中。所述方法还包括从索引存储区中的存储数据生成基于行的数据。所述方法还包括在索引存储区中创建时间索引,所述时间索引将时间值映射到检索到的对象的标识符。在其他特征中,针对检索到的对象中的每个检索到的对象,时间值指示(i)对应于检索到的对象的创建的事务时间或(ii)对应于检索到的对象的有效时间中的至少一个。所述方法还包括:高速缓存用于稍后存储在索引存储区中的附加对象;以及响应于高速缓存的大小达到阈值,将附加对象封装在一起用于批量加载到索引存储区中。所述方法还包括收集关于检索到的对象的元数据的统计信息。所述方法还包括收集关于检索到的对象的数据类型的统计信息。所述方法还包括响应于关于数据类型的统计信息,改写检索到的对象中的一些的数据。所述方法还包括响应于关于数据类型的统计信息,将检索到的对象中的一些的数据如可能未正确定类型来报告给用户。所述方法还包括收集关于检索到的对象的数据的统计信息。在其他特征中,统计信息包括最小值、最大值、平均值和标准偏差中的至少一个。所述方法还包括接收来自第一数据源的关系数据以及生成供所述动态创建使用的对象。所述方法还包括通过创建(i)指示从其中检索到关系数据中的每个项目的表格的第一列以及(ii)指示与关系数据中的每个项目相关联的时间戳的第二列来使关系数据事件化。所述方法还包括根据预定的依赖信息来指派对应于动态创建和导出的处理工作。所述方法还包括将累积模式分区成多个表格。在其他特征中,多个表格中的每一个包括在检索到的对象中一起出现的列。所述方法还包括根据在检索到的对象的对应群组中找到的列来分区累积模式,所述群组各自具有用于标识符元素的不同值。所述方法还包括记录用于检索到的对象中的每一个的源标识符。在其他特征中,对于检索到的对象中的每个对象,源标识符包括第一数据源的唯一标识符和对象在第一数据源内的位置。一种操作数据分析系统的方法包括从数据源检索对象。检索到的对象中的每一个包括(i)数据和(ii)描述所述数据的元数据。所述方法还包括针对检索到的对象中的每个对象,通过以下方式动态地创建累积模式:(i)基于对象的元数据和推断出的对象数据元素的数据类型来从对象推断模式;(ii)创建统一模式,其中所述统一模式描述(a)由推断出的模式描述的对象和(b)由累积模式描述的一组累积的对象两者;以及(iii)将统一模式存储为累积模式。所述方法还包括将检索到的对象中的每一个的数据导出到数据仓库。在其他特征中,所述方法还包括将累积模式转换为关系模式,其中导出是根据关系模式来执行的。在其他特征中,动态地创建是在第一遍通过检索到的对象期间执行的,并且其中导出是在第二遍通过检索到的对象期间执行的。在其他特征中,所述方法还包括将检索到的对象中的每一个的数据存储到索引存储服务中,其中检索到的对象中的每一个的数据从索引存储服务被导出到数据仓库。在其他特征中,所述导出包括:从索引存储服务创建至少一个中间文件,其中所述至少一个中间文件具有预定义的数据仓库格式;以及将所述至少一个中间文件批量加载到数据仓库中。在其他特征中,所述方法还包括将累积模式转换为关系模式,其中所述至少一个中间文件是根据关系模式创建的。在其他特征中,所述方法还包括通过图形用户接口从用户接收查询以及基于(i)由索引存储服务存储的数据和(ii)从数据仓库返回的结果中的至少一个来响应所述查询。在其他特征中,所述方法还包括将查询传递到数据仓库以便获得结果。在其他特征中,所述方法还包括:通过图形用户接口来向用户显示初始结果;以及随着查询执行的继续在图形用户接口中迭代地更新结果。在其他特征中,所述方法还包括:通过图形用户接口从用户接收查询;以及基于从数据仓库返回的结果来响应所述查询。在其他特征中,所述方法还包括:通过图形用户接口来从用户接收查询;在图形用户接口中向用户显示初始结果;以及随着查询执行的继续在图形用户接口中迭代地更新结果。在其他特征中,所述在图形用户接口中更新结果包括更新至少一个数据图表的至少一个轴线的定标。在其他特征中,所述方法还包括:通过图形用户接口向用户显示累积模式;在从数据源中检索到附加数据时更新累积模式;以及选择性地更新图形用户接口以反映更新的累积模式。在其他特征中,所述方法还包括在图形用户接口中,以更新的累积模式来视觉地区分改变的项目。在其他特征中,所述方法还包括响应于可从数据源得到的新对象而重复进行检索、动态创建和导出。在其他特征中,所述方法还包括:在重复导出之前,确定累积模式自从前一次导出是否已改变;以及响应于确定累积模式已改变,将至少一个命令发送至数据仓库以更新数据仓库的模式,从而反映累积模式的改变。本公开还涵盖具体化为存储在非暂时性计算机可读介质上的指令的上述方法特征中的每一个。附图说明将从具体实施方式和附图中更全面地理解本公开,在附图中:图1A描绘用于半结构化数据的利用云资源的可扩展分析平台的示例网络体系结构;图1B描绘在用户端处具有服务器设备的用于半结构化数据的可扩展分析平台的示例网络体系结构;图1C描绘用于使用数据仓库的可扩展分析平台的示例网络体系结构;图1D是服务器系统的功能框图;图2A是用于半结构化数据的示例可扩展分析平台的功能框图;图2B是实施数据仓库的示例可扩展分析平台的功能框图;图2C是实施数据仓库和混合查询执行器的示例可扩展分析平台的功能框图;图2D是示例用户接口实施的功能框图;图2E是用于半结构化数据的可扩展分析平台的示例查询系统的功能框图;图2F是使用数据仓库的示例查询系统的功能框图;图3是描绘并入所摄取的数据的示例方法的流程图;图4是描绘推断模式的示例方法的流程图;图5是描绘合并两个模式的示例方法的流程图;图6是描绘折叠模式的示例方法的流程图;图7是描绘用数据填充索引的示例方法的流程图;图8是描绘执行映射修饰的示例方法的流程图;和图9是描绘根据JSON模式创建关系模式的示例方法的流程图。图10A和图10B是描绘使用数据仓库的示例数据摄取过程的流程图;图11是描绘当使用数据仓库时响应于新数据的示例更新的流程图;图12是描绘示例用户接口操作的流程图;图13A-图13E是用户接口的示例实施的屏幕截图;图14是适应多个数据目的地的示例可扩展分析平台的功能框图;图15是从面向列的存储库导出的大部分行的图形说明;并且图16A-图16B是根据本公开的原理的用于使提取、变换、加载过程的组成部分并行化的关联图。在附图中,可重复使用参考数字来识别相似和/或相同的元件。具体实施方式概述本公开描述一种分析平台,其能够提供顺应SQL(结构化查询语言)的接口来用于查询半结构化数据。仅出于说明目的,以JSON(JavaScript对象表示法)格式表示半结构化数据。根据本公开的原理,可使用其他自描述性半结构化格式。源数据不需要是自描述性的。描述可与数据分离,正如像协议缓冲的某物的情况那样。只要存在用以将标签施加到数据的规则、试探法或包装函数,就可将任何输入数据转换为类似于JSON格式的对象。在根据本公开的分析平台的各种实施中,实现以下一些或全部优点:速度分析平台提供快速查询响应时间以支持特设、探索性和交互性分析。用户可使用这个系统来迅速地在数据中发现隐藏见解,而不必提交查询并且稍后在当天或第二天返回以查看结果。分析平台依赖于索引存储区,所述索引存储区将所有所摄取的数据存储在索引中,这实现了快速响应时间。使用两个主要索引,即BigIndex(BI)和ArrayIndex(AI),下文对它们进行更详细地描述。这些索引是路径索引与面向列的存储区之间的交叉。如同面向列存储区,它们允许查询仅在相关字段中检索数据,进而减少I/O(输入/输出)需求并且改善性能。然而,不同于列存储区,这些索引适合于具有许多字段的复杂嵌套对象和集合。对于其他访问型式,分析平台引擎维持包括Valuelndex(VI)的辅助索引,下文对其进行更详细地描述。如同传统的数据库索引,Valuelndex针对特定字段值或值范围提供快速对数访问。这些索引显著减少了检索以满足查询所必需的数据,进而改善响应时间。动态模式分析平台从数据自身中推断模式,使得用户不必先验地知道预期模式并且在可加载数据之前预先声明所述模式。半结构化数据可具有随时间和随不同源变化的结构。因此,在数据到达时,引擎动态地从数据计算并更新模式(或结构)。向用户呈现基于这种计算得到的模式的关系模式,用户可使用所述关系模式来撰写查询。不同于需要程序员在查询之前指定数据集合的模式的先前分析引擎,本平台在所有所摄取的对象当中计算(或推断)基础模式。由于动态模式性质,存在大量灵活性。生成源数据的应用可随着所述应用演进而改变结构。分析者可聚合并查询来自各个时期的数据而不需要指定模式在各个时期之间如何变化。此外,不需要设计并施行全局模式,设计并施行全局模式可能花费数月,并且常常需要排除不适合所述模式的数据。有时被描述为“无模式”的如MapReduce或Pig的其他分析系统具有两个主要缺点。第一,它们需要用户知道模式以便查询数据,而不是自动向用户呈现所推断出的模式。第二,它们对每次查询解析并解译对象及其结构,而分析平台在加载时对对象进行解析和编索引。这些索引允许更快速地运行后续查询,如上文所提及。先前引擎不提供从底层数据自动推断精确且简洁的模式。SQL分析平台暴露标准SQL查询接口(例如,符合ANSISQL2003的接口),以使得用户可利用现有SQL工具(例如,报告、可视化和BI工具)以及专门知识。因此,熟悉SQL或SQL工具的商业用户可直接访问和查询半结构化数据而不需要加载数据仓库。由于传统的基于SQL的工具不处理JSON或其他半结构化数据格式,所以分析平台呈现JSON对象的所计算得到的模式的关系视图。它呈现归一化视图并且并入优化以保持视图的大小易于管理。虽然关系视图可在所述模式中呈现若干表格,但这些表格未必被物化。为了更好地适应以表格形式表示半结构化数据,分析平台可自动识别“映射”对象。映射是可在其中搜索并查询字段名称和值的对象(或嵌套对象)。举例来说,对象可含有作为字段名称的日期以及如针对值的页面浏览量的统计信息。在关系视图中,将映射提取到单独表格中,并枢转数据以使得键在键列中并且值在值列中。扩展和弹性分析平台进行扩展以处理大数据集大小。分析平台可自动且动态地在独立节点上分布内部数据结构和处理。分析平台是针对虚拟化“云”环境来设计和构建的,所述“云”环境包括诸如AmazonWeb服务的公用云以及诸如由用户的组织管理或由第三方(诸如Rackspace)提供的虚拟化服务器环境的专用云。可利用AmazonWeb服务的各个组件,包括S3(简单存储服务)、EC2(弹性计算云)和弹性块存储(EBS)。分析平台是弹性的,这意味着其可按照需要放大和缩小到任意大小,并且可通过将其内部数据结构存储在长期存储区(诸如AmazonS3)上来休眠。分析平台还具有多租户和多用户支持。分析平台使用基于服务的体系结构,其具有四个组件:代理、元数据服务、查询执行器和存储服务。为了扩展分析平台引擎来支持较大数据集、提供较快速的响应以及支持较多用户,对执行引擎进行并行化并且在独立的低成本服务器节点上分区存储服务。这些节点在托管环境中可以是真实服务器或虚拟化服务器。由于执行器与存储服务分离,所以它们可独立扩展。这种分离的、向外扩展的体系结构允许用户利用如AWS的云环境提供的用于存储和计算的按需弹性。存储服务可配置有各种分区策略。此外,可将底层数据结构(索引和元数据)迁移到长期存储装置,如AmazonS3,以使系统在不使用时休眠,进而降低成本。同步化分析平台可被配置来自动地使其内容与来自如HDFS(Hadoop分布式文件系统)、AmazonS3(简单存储服务)和noSQL存储区(诸如MongoDB)的存储库的源数据同步并且进而复制所述源数据。可连续监视这些源以查看变化、添加和更新,使得分析平台可摄取已改变的数据。这允许查询结果是相对最新的。模式推断分析平台响应于源中出现的数据而采取以下动作:(1)从所述数据中推断统一半结构化(诸如JSON)模式,(2)创建所述模式的关系视图,(3)用数据填充物理索引,以及(4)执行利用所述索引的查询。可对动作1、2和3的一部分或全部进行流水线化以允许仅单遍通过来自数据源的数据。首先描述第一动作,即模式推断。对半结构化数据的介绍JSON是越来越流行的自描述性半结构化数据格式,并且非常普遍用于互联网上的数据交换。再次,尽管本文中描述JSON是出于说明目的并且为了提供使用JSON格式的稍后示例的上下文,但本公开并不限于JSON。简要地说,JSON对象由字符串字段(或列)和潜在不同类型的对应值构成:数字、字符串、数组、对象等。JSON对象可被嵌套并且字段可以是多值的,例如数组、嵌套数组等。可在http://JSON.org处找到说明。可在“AJSONMediaTypeforDescribingtheStructureandMeaningofJSONDocuments”(IETF(互联网工程任务组)draft-zyp-json-schema-03,2010年11月22日,可在http://tools.ietf.org/html/draft-zyp-json-schema-03处获得)中找到附加细节,所述文献的全部公开内容以引用的方式并入本文。JSON的一般化包括更多类型,例如BSON(二进制JSON)。此外,如XML(可扩展标记语言)、Protobuf、Thrift等其他半结构化格式都能转换为JSON。当使用XML时,查询可遵照XQuery而非SQL。以下是示例JSON对象:半结构化对象的结构可在对象之间有所变化。因此,在同一棒球数据中,可找到以下对象:模式描述在数据集合中找到的可能结构和数据类型。这个模式包括字段的名称、对应值的类型和嵌套关系。因此,以上两个对象的模式将为:虽然以上是本文献全文中用来说明模式的表示法,但更完整的说明是可在http://JSON-schema.org处获得的JSON模式。举例来说,JSON模式中的类型通常用引号括起来,如呈字符串或“整数(int)”形式。出于本公开的简明和易读性,将省略引号。半结构化对象可替代地视为树,其中字段作为节点并且叶子作为原子值。对象或模式中的路径是这棵树中的路径,例如“player.fname”、“teams[].name”。迭代模式推断在用户可提出数据集问题之前,他们需要知道模式,即什么字段或维度可用于查询。在许多情况下,分析者不负责生成数据,所以他们不知道什么内容已被记录并且可用。举例来说,在以上棒球示例中,如果已经仅在集合中观测到击球员,那么分析者可能不知道“ERA”字段是可用的。因此,分析平台从所摄取的数据计算(或推断)统一模式,并且呈现所述模式的关系视图来辅助分析者制定查询。分析平台旨在产生针对优化模式的精度和简洁性的模式。一般来说,精确意味着模式表示所观测或摄取的数据中的所有结构并且不允许尚未看见的结构。简洁意味着模式足够小以使得可由人类阅读和理解。动态创建模式的一般方法是以从过去对象推断出的“当前”模式开始并且随着摄取新对象而扩大模式。简单地将当前模式(S_curr)与新对象(O_new)的模式(type)合并来得到新模式(S_new):S_new=merge(S_curr,type(O_new))概略地说,合并过程采用两个模式的联合,折叠共用字段、子对象和数组,并且在出现新字段、子对象和数组时进行添加。这将在下文进行更详细地讨论。对象以下一些示例使用类似来自推特(Twitter)的数据流(被称为firehose)的输出的数据。推特firehose给出表示“已推送”推文以及关于那些推文的元数据(例如,用户、位置、主题等)的JSON对象的流(无休止序列)。这些推文类似于许多其他类型的事件日志数据,诸如现代web框架(例如,RubyonRails)、移动应用、传感器和装置(能量计、恒温器)等所产生的数据。虽然类似于推特数据,但以下示例出于解释目的而偏离实际推特数据。简单地处理基本JSON对象;仅推断对象中所看到的类型。举例来说,考虑以下对象:从那个对象推断出的模式将为:随着新对象到来,可通过对字段集执行联合来添加新字段。有时,将重复字段,但其类型改变,称为类型多态性的情形。模式使用具有相同键的多个属性来表示类型多态性。日志格式经常变化,并且开发者可添加新字段或改变字段类型。作为具体实例,考虑标识推文的“id”字段,其最初是数字。然而,随着推文数量增长,某些编程语言无法处理此类大数字,且所以已经将“id”字段改变为字符串。因此,假设看到以下形式的新记录由于现在已经看到字符串“id”,并且新字段“retweet_count”已经出现,所以如下扩大模式:请注意,“id”出现两次,一次作为字符串并且一次作为数字。有时,嵌套对象的结构发生变化。举例来说,假设添加用户的更多简档信息:在这种情况下,平台递归地合并“user”嵌套模式以得到以下模式:空值字段和空对象JSON记录中可存在空对象或空值字段。举例来说,人员坐标(纬度和经度)的记录可为:{″coordinates″:{}}模式具有相同的类型:{″coordinates″:{}}严格地说,{}称为实例,并且类型是对象。为易于解释,本公开中的示例和解释不同于严格的JSON。类似地,以下对象{″geo″:null}具有相同的类型:{″geo″:null}如果后续记录具有所述对象的值,那么通过应用合并来填写空对象。举例来说,记录:{″coordinates″:{}}{″coordinates″:{″type″:″Point″}}将产生模式{″coordinates″:{″type″:string}}空值类型类似地由所观测到的类型替换。举例来说,记录:{″geo″:null}{″geo″:true}将产生模式:{″geo″:boolean}数组推文通常含有诸如主题标签(突出的主题词)、url和其他推特用户的提及的项目。举例来说,推特firehose可自动地解析和提取这些项目以包括在推文的JSON对象中。在以下示例中,主题标签元数据用来说明如何推断数组的模式。首先,考虑在以下推文(或字符串)中提取和记录主题标签的起始偏移量列表:″#donuts#muffins#biscuits″那些偏移量可用如下数组来表示:{″offsets″:[0,8,17]}源数据中的数组在模式中表示为含有在源数组中找到的元素的类型的数组,其没有特定次序。因此,用于以上对象的模式为:{″offsets″:[number]}可能想要包括主题标签连同偏移量以用于稍后处理。在这种情况下,推文对象可如下在数组中枚举主题标签和偏移量:{″tags″:[0,″donuts″,8,″muffins″,17,″biscuits″]}对应的模式将在数组中包括两种类型:{″tags″:[number,string]}替代地,可如下颠倒标签与偏移量:{″tags″:[″donuts″,0,″muffins″,8,″biscuits″,17]}并且,因为“tags”数组可含有字符串或数字,所以所得模式为:{″tags″:[string,number]}事实上,标签文字和标签偏移量可包括在邻近对象中:{″tags″:[″donuts″,″muffins″,″biscuits″]},{″tags″:[0,8,17]}现有具有“tags”的两个模式:{″tags″:[string]}and{″tags″:[number]}在这种情况下,数组处于相同深度并且可进行合并来产生如上相同模式:{″tags″:[string,number]}另外,请注意以下模式是相同的:{″tags″:[string,number]}{″tags″:[number,string]}这是因为类型列表被视为一个集合。在可能的情况下合并数组元素的类型,并且还针对数组内部的对象和数组执行合并。在各种其他实施中,可保持类型的次序以及类型之间的关联性(数组和对象两者)。然而,这可能会使模式不太简洁。嵌套对象为了说明嵌套对象,假设如下记录开始偏移量和结束偏移量:{″tags″:[{″text″:″donuts″,″begin″:0},{″text″:″donuts″,″end″:6}]}所得模式为:{″tags″:[{″text″:string,″begin″:number,″end″:number}]}如图所示,合并对象类型来代替单独地对数组元素进行定类型。类似地,在标签字符串和偏移量处于嵌套数组中的情况下:{″tags″:[[″donuts″,″muffins″],[0,8]]}==>{″tags″:[[string],[number]]},模式还化简为:{″tags″:[[string,number]]}这是在本公开的各种实施中在模式的精度与模式的简洁性之间所做的权衡。如下处理空对象和空数组。因为如上所述来填写空对象,所以以下示例模式化简是可能的:{″parsed″:{″tag″:{},″tag″:{″offset″:number}}}=>{″parsed″:{″tag″:{″offset″:number}}类似地,针对数组使用所述合并规则,进行以下模式化简:{″tags″:[[],[number]]}=>{″tags″:[[number]]}{″tags″:[[],[[]]]}=>{″tags″:[[[]]]}{″tags″:[[],[[]],[number]]}=>{″tags″:[[[]],[number]]}=>{″tags″:[[[],number]]]}合并程序为了从先前模式和新对象创建新模式,分析平台首先对新对象进行定类型(即,计算其模式)。这个程序意图指定用于定类型的规范语义学,而不描述任何特定实施。在以下描述中,变量v、w、v_i、w_j涉及任何有效JSON值,而j、k、j_m、k_n涉及有效字符串。用于定类型的基本规则为:type(scalarv)=scalar_typeofvtype({k_1:v_1,...,k_n:v_n))=collapse({k_1:type(v_1),...,k_n:type(v_n)})type([v_l,...,v_n])=collapse([type(v_1),...,type(v_n)])第一条规则简单地陈述,针对诸如3或“a”的标量,直接从值本身(针对3的数字或针对“a”的字符串)推断对应类型。第二条规则和第三条规则使用折叠函数递归地对对象和数组进行定类型。折叠函数重复地合并对象中的相同字段的类型,并且合并数组内部的对象、数组和共用类型。其持续递归进行,直至达到标量类型为止。对于对象,折叠函数为:对于数组,折叠函数为:合并函数描述如何成对组合值来去除重复并且组合数组/映射。对于对象,合并仅递归地调用折叠来折叠共用字段:merge(v,v)=vmerge({},{k_1:v_1,...,k_n:v_n})={k_1:v_1,...,k_n:v_n}merge({j_1:v_1,...,j_n:v_n},{k_1:w_1,...,k_m:w_m})=collapse({j_1:v_1,...,j_n:v_n,k_1:w_1,...,k_m:w_m})针对数组,类似地:merge([],[v_1,...,v_n])=[v_1,...,v_n]merge([v_1,...,v_n],[w_1,...,w_m])=collapse([v_1,...,v_n,w_1,...,w_m])保留空值,诸如此处所示:merge({″coordinates″:{}},{″coordinates″:null},{″coordinates″:[]})={″coordinates″:{},″cocrdinates″:[],″coordinates″:null}JSON空值是一个值,就如同数字9是一个值。在关系式中,空值指示没有指定值。在SQL中,空值被呈现为tags<null>:boolean,其中如果存在空值,那么布尔值为真,否则为空值。为了为SQL用户简化模式,如果用户不需要区分JSON空值与SQL空值,那么可省略coordinates<null>列。累积示例使用以上简单规则,有可能对深嵌套JSON记录进行定类型。举例来说,考虑表示网页的页面浏览量统计信息的复杂假设记录:{″stat″:[10,″total_pageviews″,{″counts″:[1,[3]],″page_attr″:7.0},{″page_attr″:[internal″]}]}将产生以下模式:在各种实施中,可使用JSON模式格式来编码所推断出的模式。这种格式被标准化,并且可易于扩展为并入附加元数据(例如,对象是否为映射)。然而,这是非常冗长并且浪费空间的,所以在本公开中不用于示例。举例来说,按照JSON模式格式,如下表示以上模式:映射修饰开发者和分析者可出于许多不同目的来使用JSON对象和数组。具体地说,JSON对象常常被用作对象和“映射”。举例来说,开发者可能创建一个对象,其中字段是日期并且值是如页面浏览量的收集统计信息。另一个示例是当字段是用户id并且值是简档时。在这些情况下,对象更像映射数据结构而非静态对象。用户并不总是知道可能的字段名称,因为存在如此多的名称,并且字段名称是动态地创建的。因此,用户可能想要以查询值的相同方式查询字段。为了支持这种使用,分析平台能够识别映射。分析平台并入有试探法来识别映射,并且还允许用户指定应当将哪些嵌套对象视为映射以及不应将哪些嵌套对象视为映射。将对象标记为映射称为修饰。一般来说,在初始加载之后执行修饰,也就是说,不必在初始摄取时识别映射。可稍后在第二遍时或在已经摄取更多数据之后执行修饰。另外,如果需要的话,可简单地将映射恢复回到对象。默认地,将JSON对象视为对象(或者,按C命名法,结构体)。这可在JSON模式中通过用"bj_type":object表示对象来明确地指示。以下示例中所使用的速记表示法为O{}。为了标记映射,试探法寻找作为一个群组与其包含对象(容器)相比相对不频繁出现的字段。对于映射,使用速记Μ{}。当在第一遍计算模式时,跟踪字段出现的频率。考虑在数据集中以频率F出现的对象(或嵌套对象)。令v_i为对象中的字段i的频率,并且Ν为对象的唯一字段的数量(不管其类型如何)。比率(sum(v_i)/N)/F是平均字段频率与容器的频率的比率。如果这个比率低于阈值(诸如0.01,其可为可由用户配置的),那么包含对象被指明为映射。在各种实施中,JSON模式中的空对象被视为映射。创建关系模式在推断出源数据集中的JSON对象的模式之后,分析平台产生可暴露给SQL用户和基于SQL的工具的关系模式。目标是创建在JSON模式中表示包含关系的简洁模式,同时给予用户标准SQL的力量。这个关系模式是从被修饰的JSON模式产生的,并且是底层半结构化数据集的视图。此处呈现如何将JSON模式转换为关系视图的一些示例,之后论述用于执行转换的一般化程序。对象最简单的示例是具有简单标量类型的对象,诸如以下模式:{″created_at″:string,″id″:number,″text″:string,″source″:string,″favorited″:boolean}在这种情况下,对象的字段直接转化为关系式的列:Root(created_at:str,id:num,text:str,source:str,favorited:bool)顶层对象的关系式(或表格)在此处称为“根”,但其可由(例如)源集合的名称替换,如果这种名称存在的话。为了空间和易读性,已经将类型名称字符串、数字和布尔值缩写为str、num和bool。可将类型添加到属性名称以支持类型多态性。举例来说,考虑以下模式:{″created_at″:string,″id″:number,″id″:string,″text″:string,″source″:string,″favorited″:boolean}所得的关系模式将接着具有单独“id”和“id”列:Root(created_at:str,id<num>:num,id<str>:str,source:str,text:str,favorited:bool)嵌套对象嵌套对象产生具有外来键关系的新关系式。举例来说,考虑JSON模式:对应的关系模式为Root(created_at:str,id:num,source:str,text:str,favorited:bool,user:join_key)Root.user(id_jk:join_key,id:num,screen_name:str)嵌套对象被“归一化”为由其路径命名的单独关系式,在这种情况下为“Root.user”。表示子对象的新表格中的列"Root.user"."id_jk"是用于列“Root.user”(表格“Root”中的“user”列)的外来键。类型被指定为“joinkey”来将其与其他列区别开,但在实际实施中,join_key类型通常是整数。对象可被嵌套几级深。举例来说,转推对象可包括转推状态对象,其包括转推的用户的简档,从而得到以下模式:对应的关系视图为:请注意,“Root.user、”“Root.retweeted_status”和“Root.retweeted_status.user”全部被分离成不同表格。优化1对1关系在嵌套对象关系中,通常在主表格中的行与嵌套对象的表格中的行之间存在1对1关系。因此,这些可使用列名称的点分表示法来1对1地折叠成单个表格。举例来说,以上多关系式示例展平为:Root(created_at:str,id:num,source:str,text:str,favorited:bool,user.id:num,user.screen_name:str)并且,针对三级嵌套对象示例,请注意,由于关系模式仅仅是JSON模式的视图,所以可在不修改底层数据的情况下由分析平台按照需要向用户呈现展平、部分展平或分离(未展平)的关系模式。仅有的限制是不向用户呈现冲突的表格定义。映射在不将字段集指明为映射的情况下,对应的关系模式可包括大量列。另外,用户可能想要查询字段名称;举例来说,他们可能想要查找十二月的平均页面浏览量。为了解决这些问题,可“枢转”被修饰为映射的(嵌套)对象的表格。举例来说,考虑用于记录网站上的每个页面的各种量度(每日页面浏览量、点击量、花费时间等)的以下模式:可在关系式中将字段和值存储为键-值对,而不是产生具有针对每一天的单独列的表格:Root(page_url:str,page_id:num,stat_name:str,metric<map>:join_key)Root.metric<map>(id_jk:join_key,key:string,val:num)在这种情况下,id列是外来键;指示每个映射条目最初存在于哪个记录内。对于一年的页面浏览量,并不是在表格“Root.metric”中具有365列,而是只有两列。“key”列存储字段名称,并且“val”列存储值。举例来说,对于以上模式,数据库可含有“www.noudata.com/jobs”(page_id284)的这些记录:Root(″www.noudata.com/jobs″,284,″page_views″,3),Root.metric<map>(3,″2012-12-01″,50),Root.metric<map>(3,″2012-12-02″,30),...当映射中具有类型多态性时,枢转仍然起作用。举例来说,假设量度表示情绪,其含有类别和指示类别的强度的得分:JSON模式将为:当创建关系模式时,可将新“val”列添加到映射关系式以包括新类型。其他“val”列同样可附加有其类型以区别列名称,如所示:Root(page_url:str,page_id:num,stat_name:str,metric<map>:join_key)Root.metric<map>(id_jk:join_key,key:string,val<str>:str,val<num>:num)从以上JSON对象得到的条目将呈现为:Root.metric<map>(4,″2012-12-01″,″agreement″,NULL),Root.metric<map>(4,″2012-12-01″,NULL,5),Root.metric<map>(4,″2012-12-05″,″anger″,NULL),Root.metric<map>(4,″2012-12-05″,NULL,2)...一旦这些映射被枢转,用户就可向键列施加判断和函数,正如他们将对任何其他列所做的那样。嵌套映射基本原理对于嵌套映射来说是相同的。考虑每天和每小时的统计信息列表:所得模式将为Root(id_jk:join_key,key:string,val<map>:join_key)Root.val<map>(id_jk:join_key,key:string,val<num>:num)对象还可嵌套在映射内部:所得的展平关系模式为:Root(id_jk:join_key,key:string,val<map>:join_key)Root.val<map>(id_jk:join_key,sentiment:string,strength:number)空元素空对象有时出现在数据中。考虑以下模式:{″created_at″:string,″id″:number,″source″:string,″text″:string,″user″:{″id″:number,″screen_name″:string}}可在没有用户信息的情况下接收JSON对象,如此处所示:空用户对象可用以下关系元组表示:如果所有所摄取的用户对象在所摄取的流中具有空对象,那么所得的JSON模式将包括空对象。举例来说,见这个模式中的最终字段(“user”):{″id″:number,″user″:{}}在这种情况下,空对象“user”可被视为映射,从而得到以下关系模式:Root(id:num,user<map>:join_key)Root.user<map>(id_jk:join_key,key:string)请注意,Root.user<map>没有任何值列,并且最初是空的。然而,这种设计使得稍后在模式随着摄取新对象而改变的情况下便于添加列,因为Root中的每个记录将已经被指派联接键。数组类似于映射来处理数组,所以模式转化相当类似。主要差异是映射的字符串“key”字段由对应于数组索引的整数(int)类型的“index”字段替换。简单的示例是:{″tags″:[string]}这得到关系模式:Root(tags<arr>:join_key)Root.tags<arr>(id_jk:join_key,index:int,val<str>:str)类型多态性和嵌套数组以针对映射的相同方式起作用。考虑以下模式:{″tags″:[number,string]}这得到关系模式:Root(tags<arr>:join_key)Root.tags<arr>(id_jk:join_key,index:int,val<num>:num,val<str>:str)对象可嵌套在数组内,如此处:{″tags″:[{″text″:string,:″offset″:number}]}所得的关系模式可被创建为:Root(tags<arr>:join_key)Root.tags<arr>(id_jk:join_key,index:int,val:join_key)Root.tags<arr>.val(id_jk:join_key,text:str,offset:num)使用1对1展平优化,关系模式变为:Root(tags<arr>:join_key)Root.tags<arr>(id_jk:join_key,index:int,val.text:str,val.offset:num)嵌套数组和空数组可按与映射类似的方式针对嵌套数组和空数组创建关系模式。对于以下模式:{″tags″:[string,[number]],″urls″:[]}关系模式将为:Root(tags<arr>:join_key,urls<arr>:join_key)Root(tags<arr>(id_jk:join_key,index:int,val<str>:str,val<arr>:join_key)Root.tags<arr>.val<arr>(id_jk:join_key,index:int,val<num>:num)Root.urls<arr>(id_jk:join_key,index:int)Root.urls<arr>(id_jk:join_key,index:int)请注意,对于嵌套数组,创建单独表格,其中“val”附加到表格名称。对于空数组,创建只有“index”列而没有“val”列的单独表格,稍后一旦观测到数组的内容并对其进行定类型,就可添加“val”列。对原子值的类型推断以上类型推断和转换为关系模式的程序依赖于JSON中可用的基本类型。相同的程序同样适用于所选择的任何类型系统。换句话说,分析平台可推断像整数、浮点数和时间的较窄标量类型,只要可从值推断出原子标量类型。BSON和XML具有此类扩展类型系统。此外,可使用各种试探法(诸如正规表达式)来检测诸如日期和时间的较复杂类型。由于ANSISQL不支持与JSON相同的类型,所以将所推断出的类型转换为迄今针对关系视图所见到的最具体类型。举例来说,如果针对字段“freq”仅已经看到整数,那么将在关系模式中针对“freq”把数字类型转换为整数。类似地,如果已经观测到整数和浮点数,那么关系模式将把“freq”列示为浮点数。同样,在关系模式中字符串字段转换为字符变化类型。换句话说,可跟踪比基本JSON类型更具体的类型。替代方案是依赖于类型多态性并且使用较具体类型系统来推断数据值的类型。也就是说,代替使用JSON原始类型,使用ANSISQL的原始类型。以下是在摄取期间跟踪的类型列表(在左侧)以及如何针对SQL模式对其进行转换(在右侧)。大多数SQL数据库支持客户端可根据需要使用的包括文字在内的附加类型。请注意:ObjectId类型专用于BSON。int32,-->INTEGERint64,-->INTEGERdouble,-->DOUBLEPRECISIONstring,-->VARCHARdate,-->DATEbool,-->BOOLEANobject_id,(BSON)-->VARCHAR(24)time-->TIMEtimestamp-->TIMESTAMP程序可使用嵌套JSON模式结构的递归解包来完成从JSON模式转换为关系模式。此处示出示例实施的伪码表示。以上程序将在没有1对1优化的情况下创建关系模式。可通过所述关系模式执行第二遍,识别具有1对1关系的对象表格并且将其折叠。或者,可内联执行1对1优化,但出于清楚起见而未示出这点。当具有嵌套对象的模式的子树未被数组或映射“打断”时,然后整个对象子树可折叠成具有由其通往子树的根的路径命名的属性的单个表格。作为映射或对象的属性保持在单独表格中,但内部所含有的任何子对象可递归地折叠。这些原理适用于任何任意深度的嵌套对象。用数据填充索引一旦已经响应于新对象来更新了JSON和关系模式,就可将对象内所含有的数据存储在索引中,如下文所描述。分析平台中的索引依赖于存储键-值对的保序索引。索引支持以下操作:lookup(prefix)、insert(key,value)、delete(key)、update(key,value)以及用于范围搜索的get_next()。存在支持这种接口的许多数据结构和低级库。示例包括BerkeleyDB、TokyoCabinet、KyotoCabinet、LevelDB等。这些在内部使用保序次级存储数据结构,如B树、LSM(日志结构化合并)树和分形树。可能存在特殊情况,其中诸如针对对象ID,使用非保序索引(诸如散列表格)。使用非保序索引,可能会牺牲get_next()和进行范围搜索的能力。在各种实施中,分析框架使用LevelDB,其实施LSM树,进行压缩,并且用高插入速率向数据集提供良好性能。LevelDB还做出可能与分析框架的常用模型一致的性能权衡。举例来说,当分析诸如日志数据的数据时,将频繁地添加数据,但将很少或从不改变现有数据。有利的是,以较慢的数据删除和数据修改为代价来优化LevelDB以实现快速数据插入。保序索引具有按键次序排列键-值对的性质。因此,当在某个键附近搜索键-值对或按序检索项目时,将比在无序检索项目时快速得多地返回响应。分析平台可针对每个源集合维持多个键-值索引,并且在一些实施中,针对每个源集合维持两个到六个索引。分析平台使用这些索引来评估对关系模式的SQL查询(不需要物化SQL模式)。每个对象被指派由tid指示的唯一id。可从中重构其他索引和模式的两个索引为BigIndex(BI)和ArrayIndex(AI)。BigIndex(BI)BigIndex(BI)是存储数据中的未嵌入在数组中的所有字段的基本数据存储区。可基于col_path和tid通过键从BI检索值(val)。(col_path,tid)->valcol_path是从根对象到字段的路径,其附加有字段的类型。举例来说,对于以下记录:1:{″text″:″Tweetthis″,″user″:{″id″:29471497,″sreen_name″:″Mashah08″}}2:{″text″:″Tweetthat″,″user″:{″id″:27438992,″screen_name″:″binkert″}}以下键值对被添加到BI:(root.text<str>,1)-->″Tweetthis″}(root.text<str>,2)-->″Tweetthat″}(root.user.id<unm>,1)-->29471497(root.user.id<unm>,2)-->27438992(root.user.screen_name<str>,1)-->″Mashah08″(root.user.screen_name<str>,2)-->″binkert″在各种实施中,底层索引存储区(诸如LevelDB)不知道键的片段的重要性。换句话说,尽管“root.text<str>,1”表示根表格中的字符串文字字段的第一个元素,但索引存储区仅仅可看到无差别的多字符键。作为简单的示例,可简单地通过并置col_path和tid(重要的是,按那个次序)来创建键。举例来说,上文所示范的第一个键可被传递到索引存储区作为“root.text<str>l”。索引存储区将排列第二键(“root.text<str>2”)与第一键,这不是因为对路径相似性的任何理解,而是仅仅因为前14个字符是相同的。即使列名称和类型被存储为每个键的一部分,但由于种类排序,可使用压缩(诸如基于前缀的压缩)来降低存储成本。在BI中,源数据的所有列被组合成单个结构,这不同于针对每个新列创建单独列文件的传统列存储区。BI方法允许单个索引实例并且还使得能够延迟映射检测。由于新字段仅出现为BI中的条目,所以未能枢转映射并不会招致为稍后变为映射的每个字段创建大量物理文件的物理成本。在BI中,并置每个属性或“列”的键-值对。因此,如同列文件,BI允许查询执行器集中于查询中的关注字段上,而非迫使其扫过含有查询中未提及的字段的数据。ArrayIndex(AI)虽然可将针对数组的来自归一化表格的字段添加到BI,但数组索引接着将来自其对应值。替代地,可将数组字段添加到保留索引信息并且允许同一数组中的条目由索引存储区排列的单独ArrayIndex(AI),这为许多查询提供良好性能。可使用以下签名将数组值存储在AI中:(col_path,tid,join_key,index)->valcol_path是数组字段的路径:举例来说,用于标签数组中的元素的“root.tags”或用于标签数组内部的对象中的“text”字段的“root.tags.text”。join_key和索引是数组的外来键和值的索引。还存储tid来避免必须针对每个数组将单独条目存储在BI中。可使用tid来查找同一对象中的对应列的值。考虑不同推文中的表示主题标签的对象:1:{″id″:3465345,″tags″:[″muffins″″cupcakes″]}2:{″id″:3465376,″tags″:[″curry″″sauces″]}对于这些对象,标签表格具有以下模式:Root.tags<arr>(id_jk:join_key,index:int,val:string)对于那张表格,AI中的条目将为:(root.tags<arr>,1,1,0)-->″muffins″(root.tags<arr>,1,1,1)-->″cupcakes″(root.tags<arr>,2,2,0)-->″curry″(root.tags<arr>,2,2,1)-->″saues″数组索引允许迅速迭代通过数组字段的值。举例来说,当对这些字段执行统计(例如,总和、平均值、方差等)、查找特定值等时,这是有用的。嵌套数组实例请注意,对于根对象中的数组(顶层数组),tid和join_key字段是冗余的(见上文)并且可被优化掉。然而,对于嵌套数组,需要单独join_key,并且其不是多余的。举例来说,考虑这个JSON对象:1:{″id″:3598574,″tags″:[[8,25,75],[″muffins″,″donuts″,″pastries″]]}对应的关系模式是:Root.tags<arr>(id_jk:join_key,index:int,val<arr>:join_key)Root.tags<arr>.val<arr>(jd_jk:join_key,index:int,val<num>:num,val<str>:str)记得AI使用以下键-值对col_path,tid,join_key,index->val这得到这些AI条目tags<arr>.val<arr>,1,1,0->1tags<arr>.val<arr>,1,1,1->2(数字数组)tags<arr>.val<arr>.val<num>,1,1,0->8tags<arr>.val<arr>.val<num>,1,1,1->25tags<arr>.val<arr>.val<num>,1,1,2->75(字符串数组)tags<arr>.val<arr>.val<str>,1,2,0->″muffins″tags<arr>.val<arr>.val<str>,1,2,1->″donuts″tags<arr>.val<arr>.val<str>,1,2,2->″pastries″请注意,假如从嵌套数组键-值对中移除联接键,那么将不可能知道muffins是第一嵌套数组还是第二嵌套数组的一部分。因此,联接键对于顶层数组是冗余的,而对于嵌套数组的情况不是冗余的。数组索引2(AI2)虽然这两个索引(BI和AI)足以重构所有所摄取的数据,但它们并不有效地支持多种访问型式。对于这些访问型式,引入以下索引,可任选地创建所述索引来以附加空间为代价改善性能。这具有以下签名:(col_path,index,tid,join_key)->val其允许迅速地找到数组的特定索引元素。举例来说,使用AI2返回索引10处的所有标签(tags[10])是简单且快速的。映射索引(MI)映射索引在其功能性和签名方面类似于数组索引:(col_path,tid,join_key,map_key)->val主要差异是映射索引不是在初始摄取期间构建的,而是异步构造的。在初始加载期间,映射将被处理为对象并且照常被插入到BI中。一旦两者被填充,BI和MI两者中有许多条目可用以实现较有效的查询处理。BI条目保持相关,以防用户或管理员要求解除修饰映射。只需要改变关系模式,并且接着将在查询中使用对应于未映射数据的原始BI条目。如同AI,当迭代通过映射的元素时,MI是有用的:用于应用统计函数、用于局限于特定字段名称等。再次考虑维持页面浏览量统计信息的对象:1:{″url″:″noudata.com/blog″,″page_views″:{2012-12-01″:10,″2012-12-02″:12,...″2012-12-15″:10}2:{″url″:″noudata.com/jobs″,″page_views″:{″2012-12-01″:2,″2012-12-02″:4,...″2012-12-15″:7}在标记为映射的情况下用于page_views表格的关系模式为:Root.page_views<map>(id_jk:join_key,key:string,val:num)其中键是映射的键,并且val是相关联的值。对于以上对象,MI中的条目将为:(root.page_views<map>,1,1,″2012-12-01″)-->10(root.page_views<map>,1,1,″2012-12-02″)-->12…(root.page_views<map>,1,1,″2012-12-15″)-->10(root.page_views<map>,2,2,″2012-12-01″)-->2(root.page_views<map>,2,2,″2012-12-02″)-->4…(root.page_views<map>,2,2,″2012-12-05″)-->7这种排序允许针对每个页面排列page_views映射中的值,而在BI中,将通过日期来排列所述值。映射索引2(MI2)另外,可实施辅助映射索引。映射索引在其功能性和签名方面类似于数组索引:(col_path,map_key,tid,join_key)->val这允许有效搜索特定映射元素,诸如“对应于映射键2012-12-05的所有不同值”。可如下书写AI2和MI2两者的一般表示:(col_path,key,tid,join_key)->val其中键对应于数组的索引或映射的map_key。ValueIndex(VI)虽然以上索引对于查找特定字段的值并且迭代通过那些值是有用的,但如果查询正仅查找特定值或值范围,那么其不允许快速访问。举例来说,查询可要求返回由“mashah08”书写的推文的文字。为了辅助此类查询,可针对模式中的一些或所有字段构建ValueIndex。ValueIndex可在摄取数据时构建或稍后异步构建。值索引的键为:(col_path,val)其中val是源数据中的属性的值。VI中的那个键的对应值取决于在哪里出现所述值的字段。对于以上每个索引,其改变:BI:(col_path,val)-->tidAI:(col_path,val)-->tid,join_key,indexMI:(col_path,val)-->tid,join_key,key举例来说,推文:1:{″text″:″Tweetthis″,″user″:{″id″:29471497,″screen_name″:″mashah08″}}2:{″text″:″Tweetthat″,″user″:{″id″:27438992,″screen_name″:″binkert″}}被存储为:(root.text<string>,″Tweetthis″)-->1(root.text<string>,″Tweetthat″)-->2(root.user.id<num>,29471497)-->1(root.user.id<num>,27438992)-->2(root.user.screen_name<string>,″Mashah08″)-->1(root.user.screen_name<string>,″binkert″)-->2使用VI,可通过查找键:(root.user.screen_name,“mashah08”)并且检索所有关联tid来搜索由“mashah08”创作的所有推文。接着,可使用检索到的tid来搜索BI以返回每条推文的对应文字。索引且尤其是值索引的成本是附加存储空间以及在将新对象添加到系统时对其进行更新所需要的执行时间。由于空间或更新开销的缘故,用户可能由于这些原因而不想对所有可能路径进行索引。因此,用户可指定在VI中对哪些路径进行索引。RowIndex(RI)为了有助于重现整个所摄取的对象(类似于在传统的基于行的存储区中请求记录),可实施RowIndex(RI)。RowIndex存储键-值对tid-->JSONobjectJSON对象可被存储为字符串表示、BSON或任何其他串行化格式,诸如用于JSON对象的内部表示的树结构。对于上文相对于VI所论述的两条推文,对应的RI条目将为:1-->{″text″:″Tweetthis″,″user″:{″id″:29471497,″screen_name″:″mashah08″}}2-->{″text″:″Tweetthat″,user″:{″id″:27438992,″screen_name″:″binkert″}}实例BI、AI、MI和VI的实例。考虑与上文类似的推文,其中添加了“retweet_freq”属性,所述属性记录一条推文在一天内被转推多少次:这些记录的模式为:这些记录的JSON模式将为如果retweet_freq未被视为映射,那么关系模式为:Root(text:str,user.id:num,user.screen_name:str,tags<arr>:join_key,retweet_freq.2012-12-01:num,retweet_freq.2012-12-02:num,retweet_freq.2012-12-03:num,retweet_freq.2012-12-04:num,retweet_freq.2012-12-05:num)Root.tags<arr>(id_jk:join_key,index:int,val:str)在这种情况下,以上示例性记录将如下填充这些关系式:Root:(″Love#muffins...″,29471497,mashah08,1,10,13,1,NULL,NULL)(″Love#sushi...″,28492838,binkert,2,NULL,NULL,NULL,20,1)Root.tags<arr>:(1,0,″muffins″)(1,1,″cupcakes″)(2,0,″sushi″)(2,1,″umami″)请注意,这些是在假如对这些表格运行“select*”查询的情况下查询将返回的元组。这些元组不必在存储引擎中如此物化。也就是说,这可仅为底层数据的虚拟视图,而不如所描绘那样进行物理存储。如果retweet_freq被识别为映射,那么关系模式变得更简洁(并且更适应附加数据),如下:Root(text:str,user.id:num,user.screen_name:str,tags<arr>:join_key,retweet_freq<map>:join_key)Root.tags<arr>(id_jk:join_key,index:int,val:str)Root.retweet_freq<map>(id_jk:join_key,key:str,val:num)对应的元组为:Root:(″Love#muffins...″,29471497,mashah08,1,1)(″Love#sushi...″,28492838,binkert,2,2)Root.tags<arr>:(1,0,″muffins″)(1,1,″cupcakes″)(2,0,″sushi″)(2,1,″umami″)Root.retweet_freq<map>:(1,″2012-12-01″,10)(1,″2012-12-02″,13)(1,″2012-12-03″,1)(2,″2012-12-04″,20)(2,″2012-12-05″,1)添加到BI的键-值对为:(root.retweet_freq.2012-12-01,1)-->10(root.retweet_freq.2012-12-02,1)-->13(root.retweet_freq.2012-12-03,1)-->1(root.retweet_freq.2012-12-04,2)-->20(root.retweet_freq.2012-12-05,2)-->1(root.text,1)-->″Love#muffinsand#cupcakes″(root.text,2)-->″Love#sushiand#umami″(root.user.id,1)-->29471497(root.user.id,2)-->28492838(root.user.screenname,1)-->mashah08(root.user.screen_name,2)-->binkert添加到AI的键-值对如下。请注意,在这种情况下,联接键是冗余的(与tid一样),因为没有嵌套数组。(root.tags<arr>,1,1,0)-->″muffins″(root.tags<arr>,1,1,1)-->″cupcakes″(root.tags<arr>,2,2,0)-->″sushi″(root.tags<arr>,2,2,1)-->″umami″RI将具有以下两个条目如果构建MI并且在构建MI时,MI将具有以下条目:(root.retweet_freq<map>,1,1,″2012-12-01″)-->10(root.retweet_freq<map>,1,1,″2012-12-02″)-->13(root.retweet_freq<map>,1,1,″2012-12-03″)-->1(root.retweet_freq<map>,2,2,″2012-12-04″)-->20(root.retweet_freq<map>,2,2,″2012-12-05″)-->1类似地,VI将具有以下条目(如果所有路径被索引并且映射被像映射一样处理):(root.retweet_freq<map>,1)-->2,2,″2012-12-05″(root.retweet_freq<map>,1)-->1,1,″2012-12-03″(root.retweet_freq<map>,10)-->1,1,″2012-12-01″(root.retweet_freq<map>,13)-->1,1,″2012-12-02″(root.retweet_freq<map>,20)-->2,2,″2012-12-04″(root.tags<arr>,″cupcakes″)-->1,1,1(root.tags<arr>,″muffins″)-->1,1,0(root.tags<arr>,″sushi″)-->2,2,0(root.tags<arr>,″umami″)-->2,2,1(root.text<str>,″Love#muffinsand#cupcakes″)-->1(root.text<str>,″Love#sushiand#umami″)-->2(root.user.id,29471497)-->1(root.user.id,28492838)-->2(root.user.screen_name,″mashah08″)-->1(root.user.screen_name,″binkert″)-->2虽然分阶段描述以上动作,但以上动作可被流水线化以允许在单个遍次中执行摄取,加载BI、AI和RI,并且计算JSON模式。可异步构建其他索引,并且可根据需要启用和停用其他索引。系统体系结构分析平台被建造为面向服务的。在各种实施中,存在五项主要服务:代理、元数据服务、查询执行器、存储服务和摄取服务。这种分离方法可具有若干优点。由于这些服务仅通过外部API(远程过程调用)进行通信,所以可对服务进行多路复用并且独立共享每个服务。举例来说,可每个执行器使用多个代理并且每个存储服务使用多个执行器。还可在执行器和存储服务的多个实例上共享元数据服务。执行器、存储和摄取服务被并行化,并且可在专用或公用基础设施中在虚拟化机器实例中运行单独片段。这允许独立地中止并扩展这些服务。这对于通过基于需求波动调整服务能力来降低成本为有用的。举例来说,公用云的弹性可用以高度并行化摄取服务来实现快速夜间加载,同时针对日常查询工作负荷保持执行和存储服务在大小上减小。代理是通往客户端的网关并且支持一个或多个标准协议,诸如ODBC(开放式数据库连接)、libpq、JDBC(Java数据库连接)、SSL(安全套接字层)等。网关充当内部服务的防火墙、验证服务和控制点。举例来说,客户端连接(诸如网络套接字)可在代理处保持打开,而中止支持的执行和存储服务以节省成本。当客户端连接再次变得有效时,可按照需要以相对较短的启动等待时间唤醒所需要的服务。元数据服务通常由其他服务的许多实例共享。它存储元数据,包括模式、源信息、分区信息、客户端用户名、键、统计信息(直方图、值分布等)以及关于每个服务的当前状态的信息(实例数量、IP地址等)。存储服务管理索引并且服务读取和写入请求。另外,查询执行器可将许多函数下推到存储服务。在各种实施中,存储服务可评估判断和UDF(用户自定义函数)以过滤结果,评估本地联接(例如,以重构对象),评估下推联接(例如,广播联接),并且评估本地聚合。存储服务可通过称为分区并行的技术来并行化。在这种方法中,创建存储服务的许多实例或分区并且在分区当中划分所摄取的对象。每个分区存储每个类型的索引,就像它是单个整体实例一样。然而,每个分区仅对所摄取的数据的子集进行索引。分析引擎支持一个或多个分区策略。简单但有效的策略是通过tid来分区对象并且将其相应条目存储在本地索引中。以此方式,不在不同实例上分裂所摄取的对象,当查询依赖于对象的多个部分时,所述分裂可能会消耗显著的网络带宽。可按多种方式指派tid,包括散列指派、轮循或基于范围的指派。这些特定指派在所有实例上分布最新近的数据,进而分摊负荷。另一种策略是通过另一字段值(或字段值组合),诸如用户id或会话id来分区。替代分区字段(列)使得便于与其他表格或集合(例如,用户简档)执行本地联接。分区策略可为散列分区或使用取样和范围分区。前者用于有效点查找,并且后者用于支持有效范围搜索。不管分区策略如何,应当能够本地重构对象或对象的任何子集。因此,存储服务分区在查询处理期间没有串扰,并且仅需要通过其API来与执行服务通信。存储服务具有高速缓存。可增加每个分区中的高速缓存大小或增加分区数量来改善存储服务的性能。存储服务可将索引高速缓存在存储器中或本地磁盘上,并且索引可驻存于如AmazonS3的外部存储装置上。这种特征允许关闭和毁坏存储服务节点并且在必要时对其进行重新部署。此外,它允许极端弹性:以低成本使存储服务休眠到S3并且随着需求波动而改变存储服务能力的能力。查询执行服务执行由查询规划阶段生成的查询计划。它实施查询运算符,例如联接、统一、分类、聚合等。这些运算中的许多运算可被下推到存储服务,并且在可能时这样做。这些包括判断、投影、用以重构所投影的属性的列式联接以及使用分组依据声明的分配和代数聚合函数的部分聚合。查询执行服务接受来自存储服务的数据并且计算非本地运算:非本地联接、需要重新分区的依据声明的分组、分类等。所述执行器类似于分区的并行执行器。它使用交换运算符来在查询执行步骤之间重新分区,并且采用本地存储来溢出中间结果。对于许多查询,有可能在存储服务中运行大多数查询并且仅需要单个执行器节点来收集结果并执行任何小型非本地运算。摄取服务摄取服务负责将半结构化数据加载到存储服务中,在存储服务处可查询所述数据。用户提供来自多种平台(例如,MongoDB、AmazonS3、HDFS)的呈多种格式(例如,JSON、BSON、CSV)的数据,所述数据任选地用压缩机制(例如,GZIP、BZIP2、Snappy)进行压缩。基本程序都适用而不管所使用的格式如何。摄取任务可粗略地划分为两个部分:初始摄取任务,其加载大量新用户数据;以及增量摄取,其在新数据可用时周期性地发生。初始摄取初始摄取过程可被分解为若干个步骤。首先,将输入数据分区为多个数据块。用户在文件集合中或通过提供通往其数据源的直接连接来提供初始数据。在元数据服务中记录这些文件的位置和格式。用户可提供已经例如由于日志文件旋转而被分区的数据,但是如果没有,那么可将文件分区为多个数据块以支持并行加载。这些数据块通常为大约几百兆字节并且独立进行处理。用于分区输入文件的确切机制取决于数据格式。对于由换行符分离记录的未压缩格式(例如,JSON或CSV),可使用数量等于目标数据块数量的过程来并行处理单个文件。处理在文件中的适当偏移量(file_size/total_num_chunks)*chunk_num处开始,并且接着进行搜索,直至找到换行符为止。对于压缩数据或呈像BSON的二进制格式的数据,可能需要依序扫描每个输入文件。将每个数据块的位置(文件,偏离量,大小)存储在元数据服务中。一旦将数据划分为多个数据块,就执行实际模式推断和摄取。作为这个过程的一部分,启动两个服务:摄取服务和存储服务。这两个服务可采用多个服务器来工作。所述两个服务还可共同位于任何给定机器上。摄取服务是短暂的并且仅在摄取过程期间使用,而存储服务保持实际数据并且必须是持久的。摄取中所涉及的服务器将数据发送到存储服务服务器,并且摄取服务器的数量独立于存储服务器的数量,其中选择数量来使每个服务的吞吐量之间的不平衡减到最小。在摄取服务器之间分区数据块。每个摄取服务器负责用于指派给它的每个数据块的以下步骤:(i)解析和类型推断,(ii)与存储服务通信,以及(iii)计算局部模式和统计信息。首先,将数据记录解析成内部树表示。可针对所有源格式(JSON、BSON等)使用一致的内部表示。根据输入格式,还可执行类型推断。举例来说,JSON没有日期的表示,所以通常将日期存储为字符串。由于日期是非常常见的,所以其是对在摄取期间检测的类型的示例上,使得用户可利用日期发布查询。对于CSV输入文件,由于没有对列进行定类型,所以必须还检测诸如整数的基本类型。一旦已经对记录进行解析并且推断出类型,就将解析树的压缩表示发送到存储服务。这采用树的前序遍历的形式。存储服务负责确定待存储在每个索引(BI、AI等)中的值,并且产生元组id和联接键。键产生被推迟给存储服务,使得可依序产生键,这对底层索引存储区改善摄取性能。在摄取记录时,使用上述规则更新局部JSON模式。所述模式将反映单个摄取机器所看到的记录,并且不同机器可具有不同模式。除了计算模式之外,还维持统计信息,所述统计信息对查询处理以及识别映射有用。这些统计信息包括像每个属性出现的次数以及其以字节数计的平均大小的量度。举例来说,以下记录{id:3546732984}{″id:″3487234234″}{id:73242342343}{id:458527434332}{id:″2342342343″}将产生模式{id:int,id:string},并且可用计数3标注id:int并且用计数2标注id:string。每个摄取机器存储其在元数据服务中计算出的模式和统计信息。一旦已经摄取所有数据块,就计算总体模式,其将由查询引擎使用并且呈现给用户。这可使用单个进程来完成,所述单个进程从元数据服务读取部分模式,使用上述方法对其进行合并,并且将结果存储回元数据服务中。由于模式的数量限于摄取机器的数量,所以这个过程不是性能关键的。确定映射是任选的。如先前所描述,可连同存储在元数据服务中的统计信息一起使用试探法来确定应当在MI中将哪些属性存储为映射。记得这对查询处理来说是不必要的,但这使得一些查询表达起来较自然并且改善效率。一旦已经识别了映射,每个存储服务器就接收识别哪些属性应当是映射的消息。存储服务器接着扫描这些列并且将它们插入到MI中。增量更新一些用户可预先加载其大部分数据,但大多数用户将随时间周期性加载新数据,通常作为规则(例如,每小时或每天)过程的一部分。摄取这个数据很大程度上类似于初始摄取。将新数据分裂成数据块,针对每个数据块计算模式,并且将局部模式与元数据服务中所维持的全局模式合并。在添加新数据时,系统自动地检测新数据。方法取决于源数据平台。举例来说,对于S3文件,最简单的情况是检测S3桶中的变化。特殊过程周期性地扫描桶以查找新键-值对(即,新文件),并且将所找到的任何键-值对添加到元数据服务。在已经找到某个数量的新文件或已经过去某个时间段之后,进程启动新摄取进程来加载所述数据。在MongoDB中执行的操作可存储在称为操作日志(或oplog)的特殊集合中。oplog提供在内部用于复制的由MongoDB使用的写入操作的一致记录。读取oplog并且将其用于在存储新记录的S3中创建一组平面文件。以上方法可接着用以摄取新数据。增量摄取过程可处理新数据(例如,新JSON文献)以及对现有文献的更新(例如,现有JSON文献中的新属性或现有属性的新值)。每个数据源平台在暴露源文件中的更新的方面具有不同能力。将这种类型的信息称为“德尔塔(delta)”,并且其可采用平面文件或日志文件(例如,MongoDB)的形式。增量摄取过程处理来自“德尔塔”文件的信息,并且将所述信息与现有模式信息进行组合来产生发送到存储服务的新数据。构造数据子集尽管此处描述的用于摄取数据并且进行增量更新的系统可从源摄取全部数据,但通过预先指定想要摄取的数据的JSON模式(或关系模式),仅摄取子集是相对简单的。这通过提供JSON模式本身或通过提供指定子集的查询来进行。以此方式,分析平台可被认为是源数据的物化视图。还有可能指定用户不想摄取的数据。可提供JSON模式或关系模式,其描述不应摄取的数据部分。接着,只不过是在元数据服务中记录那个信息,其告诉摄取过程简单地跳过所有未来行的那些元素。如果这在已经摄取了数据之后进行,那么已经摄取的数据简单地变为不可用并且可成为由后台任务收集的垃圾。这个垃圾收集过程将被并入到索引存储区(例如,LevelDB)的压缩过程中。容错性尽管有可能在初始摄取期间重新开始加载过程,但增量摄取过程不应破坏系统中的现有数据,以便防止用户必须从头开始重新加载所有数据。由于摄取文件不是幂等操作,所以归因于id生成,可基于获取底层存储系统的快照来实施简单容错方案。当底层存储系统支持在一个时间点获取一致快照时,获取快照可为简单的,正如LevelDB那样。使用这个基元,用于递增加载的步骤如下。单个进程指导每个存储服务器在本地获取快照并且在加载的持续时间内将所有查询指向这个快照。如上所述加载每个数据块。当完成时,负责加载数据块的摄取服务器将其标记为在元数据服务中完成。一个进程监视元数据服务。当已经加载所有数据块时,其自动将查询重新指向状态的更新版本。接着可丢弃在第一个步骤中获取的快照。在失败的情况下,快照成为状态的规范版本,并且丢弃状态的部分经更新的(并且可能被破坏的)原始版本。接着重新开始摄取过程。另外,可在服务器发生故障的情况下使用存储系统磁盘卷的快照来进行恢复。查询执行示例查询为了示出示例执行,考虑以下简单查询:selectcount(*)fromtableastwheret.a>10;首先,代理接收查询并且将其发送到执行器节点以用于规划。接下来,执行器节点创建查询计划,其调用元数据服务来确定哪些集合和存储节点可供使用。所述执行器节点通常将所述计划分配给其他执行器节点,但此处,仅需要单个执行器节点。执行节点接着向存储服务节点发出RPC调用,下推t.a>10判断和计数函数。接下来,存储节点计算子计数并且将其返回到执行器节点。执行器节点接着在代理取下一个结果值时将结果返回到代理。动态定类型数据库系统(例如,PostgreSQL)的存储引擎是强定类型的,这意味着列(或属性)的所有值必须具有完全相同的类型(例如,整数、字符串、时戳等)。在大数据分析的上下文中,这是一个重要限制,因为经常应用需要改变一条特定信息(属性)的表示以及因此它们使用来存储所述信息(属性)的数据类型。举例来说,应用可最初使用整数来存储特定属性的值并且接着切换到使用浮点数。数据库系统未被设计来支持此类操作。一种处理这个问题的方式是针对每个属性使用多个关系列-每个不同数据类型使用一个。举例来说,如果已经看到具有值31432和“31433”(即,整数和字符串)的属性“user.id”,那么可将“user.id<int>”和“user.id<string>”存储为单独列。单个记录将具有仅针对这些列中的对应于那个记录中的“user.id”的类型的一个列的值。针对那个记录的其他列的值将为空值。针对同一属性呈现多个列通常对于用户使用来说太复杂。为了简化用户体验,分析平台可在查询时动态地推断用户期望使用的类型。为此,存储服务记录多个类型。举例来说,存储服务针对数字使用一般数据类型,称为NUMBER,其涵盖整数和浮点数。当使用NUMBER类型时,将较具体的数据类型存储为值的一部分。举例来说,将属性“Customer.metric”的整数值10在BI中存储为键-值对,其中(Customer.metric,<NUMBER>,tid)是键并且(10,INTEGER)是值。同一属性的浮点值10.5将被存储为键:(Customer.metric,<NUMBER>,TID)、值:(10.5,FLOAT)。最后,在查询时,分析平台可根据查询的性质(判断、挑选操作等)在数据类型之间执行动态挑选,只要这些操作不导致信息损耗。虽然“number”不是ANSISQL类型,但灵活的定类型系统允许客户端根据查询上下文将其处理为标准ANSISQL浮点数、整数或数字类型。举例来说,考虑以下查询:selectuser.langfromtweetswhereuser.id=′31432′在具有“user.id<int>”和“user.id<string>”两者的情况下,系统在查询时任选地将整数(例如,31432)转换为单个字符串表示(例如,“31432”),进而允许用户对具有ANSISQL类型VARCHAR的单个列“user.id”起作用。虽然提到ANSI(美国国家标准协会)/ISO(国际标准化组织)SQL:2003作为示例,但在其他实施中,可遵守其他标准,即SQL或其他。仅举例来说,暴露的接口可符合ANSI/IS0SQL:2011。附图在图1A中,示出分析平台的示例基于云的实施。使用分析框架的组织的局域网(LAN)或广域网(WAN)100连接到互联网104。这个实施中的计算需求和存储需求均由基于云的服务提供。在所示出的特定实施中,计算服务器与存储服务器分离。具体地说,计算云108包括多个服务器112,其提供分析框架的处理能力。服务器112可为离散硬件实例或可为虚拟化服务器。服务器112还可具有其自己的存储装置,处理能力对所述存储装置进行操作。举例来说,服务器112可实施查询执行器和存储服务两者。尽管传统的列式存储系统将数据作为列存储在磁盘上,但当将所述数据读取到存储器中时,从列式数据重组行。然而,本公开的索引在磁盘上和在存储器中均作为列式存储进行操作。由于索引的独特配置,可用相对较少的损失来实现快速列式访问的利益。存储云116包括用于索引数据的存储阵列120,因为根据本公开,将数据存储在索引中而非存储在物化表格中。当使用服务器112的存储资源时,存储阵列120可用于备份和近线存储,而非用于对每个查询做出响应。在各种实施中,存储阵列124可包括数据,分析框架将对所述数据进行操作。仅举例来说,存储阵列124可保持相关数据,诸如日志数据,用户可能想要使用分析框架来查询所述数据。虽然存储阵列120和存储阵列124被示出为在同一存储云116中,但其可位于不同云中,包括专用外部托管云、公用云和组织特定的内部托管虚拟化环境。仅举例来说,存储云116可为AmazonWeb服务(AWS)S3云,商家已经正在使用所述云来在存储阵列124中存储数据。因此,将数据传送到存储阵列120中可用高吞吐量和低成本来实现。计算云108可由AWSEC2提供,在所述情况下,计算云108和存储云116由共同提供商托管。用户130使用标准SQL工具构造查询,在计算云108中运行那个查询,并且向用户130返回响应。SQL工具可为已经安装在用户130的计算机134上的工具,并且不必为了与本分析框架一起工作来进行修改。在图1B中,示出另一种示例部署方法。在这种情况下,物理服务器设备180连接到商家的LAN/WAN100。服务器设备180可现场进行托管或可异地进行托管,并且诸如使用虚拟专用网络,连接到LAN/WAN100。服务器设备180包括计算能力以及存储装置,并且从源接收输入数据,所述源可在LAN/WAN100本地。仅举例来说,计算机或服务器184可存储日志,诸如web流量日志或入侵检测日志。服务器设备180检索并且存储索引数据以用于对用户130的查询做出响应。存储云116可包括附加数据源188,其可保持另外其他数据和/或可为用于较旧数据的近线数据存储设施。为了满足用户查询,服务器设备180可从附加数据源188检索附加数据。诸如出于备份目的,服务器设备180还可将数据存储在存储云116中。在各种其他实施中,附加数据源188可为云中的Hadoop实施的一部分。本公开的分析框架是灵活的,以使得许多其他部署情形是有可能的。仅举例来说,可向商家提供软件,并且可将那个软件安装在拥有的或托管的服务器上。在另一实施中,可提供虚拟机实例,其可通过虚拟化环境来例示。此外,用户可在浏览器中具备用户接口,并且SQL部分可由服务提供商(诸如NouData)托管,并且在其系统上或在云中实施。数据仓库在图1C中,示出根据本公开的原理的示例部署方法。除了或代替存储在索引存储装置120中,还可将摄取数据存储到数据仓库192中。在各种实施中,数据仓库192可位于客户位置处或如图1C中所示位于云196中。使用数据仓库192可提供多种益处。仅举例来说,数据仓库192通常将具有成熟且全功能的查询处理层和ODBC接口。此外,数据仓库192可以是用于除了将由根据本公开的系统摄取的数据外的其他数据的中央存储库。另外,数据仓库192可实施数据的快照拍摄和修订控制,并且还可以是所建立的备份策略的一部分。在各种实施中,数据仓库192可以仅为关系数据库,诸如支持SQL命令的子集或全集的关系数据库,包括PostgreSQL、MySQL、微软SQL服务器、Oracle等。因为所摄取的数据的模式可随时间而改变,所以使用列式存储实施数据仓库192可允许可有效添加的附加列(诸如新属性或现有属性的新类型)。在面向行的传统数据库系统中,添加列可为时间和/或空间效率低下的。数据仓库192的各种实施可具有列式特征,包括来自Vertica、Greenplum、Aster/Teradata和Amazon(RedShift)的产品。数据仓库192的一些实施,诸如Vertica和AmazonRedShift,支持并行加载,以使得可从若干个源同时摄取正确格式化的数据。通过将数据封装到多个中间文件中,可显著减少将数据加载到数据仓库192中所需的时间。在云196中实施数据仓库192可提供各种优点,诸如减少与购买用于数据仓库192的硬件和软件相关联的前期成本。另外,服务数据仓库192的云196可能够从索引存储装置120或数据源124摄取数据,其中通过互联网104的公共部分可得到更大的吞吐量。在各种实施中,诸如当数据仓库192是AmazonRedShift并且索引存储装置120存储在AmazonS3中时,可在索引存储装置120与数据仓库192之间传送数据而不会离开Amazon的网络。这可允许减少的等待时间和增加的吞吐量。在图1D中,示出服务器200的硬件组件。处理器204执行来自存储器208的指令并且可对存储在存储器208中的数据进行操作(读取和写入)。一般来说,针对速度来说,存储器208是易失性存储器。处理器204潜在地通过芯片组212与非易失性存储装置216进行通信。在各种实施中,非易失性存储装置216可包括充当高速缓存的快闪存储器。容量较大且成本较低的存储装置可用于次级非易失性存储装置220。举例来说,磁存储介质诸如硬盘驱动器可用于将底层数据存储在次级非易失性存储装置220中,所述次级非易失性存储装置的有效部分高速缓存在非易失性存储装置216中。输入/输出功能性224可包括诸如键盘和鼠标的输入装置以及诸如图形显示器和音频输出装置的输出装置。服务器200使用联网卡228与其他计算装置通信。在各种实施中或在各种时间,输入/输出功能性224可休眠,其中服务器200与外部行动者之间的所有交互是通过联网卡228进行的。为了易于说明,未示出附加众所周知的特征和变化,诸如(仅举例来说)非易失性存储装置216与存储器208之间或联网卡228与存储器208之间的直接存储器存取(DMA)功能性。数据流在图2A中,流程图示出如何将数据摄取到分析框架中以使得其可由用户130查询的一个示例。数据源300提供数据,分析框架对所述数据进行操作。如果那个原始数据不是自描述性的,那么任选的用户自定义包装函数304可将原始数据转换为自描述性半结构化数据,诸如JSON对象。管理员308(其可为以不同能力进行操作的用户130)能够指明用于实施这些包装函数的指导方针。管理员308还可指明将使用哪些数据源300以及将从那些数据源检索什么数据。在各种实施中,检索数据可包括取子集操作和/或其他计算。仅举例来说,当一个数据源300是Hadoop时,可在针对分析框架检索数据之前请求MapReduce工作。通过模式推断模块312对检索到的数据进行处理,所述模式推断模块312基于所接收数据的所观测结构来动态地构造模式。在各种实施中,管理员308可具有向模式推断模块312提供定类型提示的能力。举例来说,定类型提示可包括对辨认特定格式(诸如日期、时间或其他管理员定义的类型)的请求,所述格式可由(例如)正规表达式指定。将数据对象和由模式推断模块312产生的模式提供到修饰模块316以及索引创建模块320。输入对象包括源数据以及描述所述源数据的元数据。由索引创建模块320将源数据存储在索引存储装置324中。修饰模块316在由模式模块312产生的模式中识别映射。在不需要映射识别的实施中,可省略修饰模块316。管理员308可能够指定映射标准来调整在识别映射的过程中使用的由修饰模块316执行的试探法。在已经识别了映射之后,关系模式创建模块328产生关系模式,诸如顺应SQL的模式。另外,将所识别的映射提供给辅助索引创建模块332,其能够创建附加索引,诸如MapIndex,以及ValueIndex中的映射条目,如上所述。辅助索引还可存储在索引存储装置324中。管理员308可具有请求创建映射索引的能力,并且可指定将哪个列添加到值索引。另外,管理员可能够指定应当将哪些对象处理为映射,并且可动态地改变是否将对象处理为映射。此类改变将导致关系模式的改变。关系优化模块336优化关系模式以向用户130呈现较简洁的模式。举例来说,关系优化模块336可识别表格之间的一对一关系,并且将那些表格展平为单个表格,如上所述。将所得的关系模式提供给元数据服务340。查询执行器344与元数据服务340对接以执行来自代理348的查询。代理348与顺应SQL的客户端(诸如ODBC客户端352)交互,所述客户端在没有特殊配置的情况下能够与代理348交互。用户130使用ODBC客户端352来将查询发送到查询执行器344并且接收对那些查询的响应。通过ODBC客户端352,用户130还可看到由元数据服务340存储的关系模式并且在所述关系模式上构造查询。不要求用户130或管理员308知道预期模式或帮助创建模式。替代地,基于检索到的数据来动态地创建模式,并且接着呈现所述模式。尽管示出ODBC客户端352,但除了ODBC之外的机制也是可用的,包括JDBC和直接postgres查询。在各种实施中,图形用户接口应用可有助于方便用户使用ODBC客户端352。查询执行器344对来自存储服务356的数据进行操作,所述存储服务356包括索引存储装置324。存储服务356可包括其自己的本地存储处理模块360,查询执行器344可将各种处理任务委派给所述本地存储处理模块360。接着由存储处理模块360将所处理的数据提供给查询执行器344以构造对所接收的查询的响应。在基于云的实施中,存储服务356和查询执行器344均可在计算云中实施,并且索引存储装置324可存储在计算实例中。索引存储装置324可镜像到近线存储装置,诸如在如图1A中所示的存储云116中。在图2B中,数据加载模块370生成呈数据仓库192所理解的格式的数据文件。举例来说,数据仓库192可支持来自用于加载大量数据的命令的SQL副本。由这个命令进行操作的数据文件可具有预定义的类型,所述类型可为CSV(逗号分隔变量)的变体。针对关系模式中的每个关系,创建用于加载到数据仓库192中的中间文件。当数据仓库192支持并行加载时,一些或所有较大文件可以拆分成用于并行加载的多个文件。用于这些中间文件的数据可从索引存储装置124中检索和/或从数据源300的第二遍执行中检索。用户接口374向用户130提供对数据仓库192的访问。仅举例来说,用户接口374可提供为数据仓库192的一部分。在其他实施中,用户接口374可将命令传递至数据仓库192和/或可创建用于由数据仓库192执行的SQL命令。在图2C中,用户接口376通过代理348与查询执行器344通信。查询执行器344可将某些查询传递到数据仓库192。对于各种查询,查询执行器344可基于来自存储处理模块360和元数据服务340的数据来执行查询的一部分,并且将查询的其他部分传递到数据仓库192。查询执行器344可将结果组合并且将组合的输出传递到代理348。在各种实施中,用户接口376可以使某些关系或数据是存储在数据仓库192还是索引存储装置324中对用户130来说是透明的。这种特征可与已具有存储在数据仓库192中的一些数据并且正将新数据加载到索引存储装置324中、或相反情况的客户相关。在图2D中,示出用户接口376的示例实施的高级功能框图。模式表示模块378接收来自模式监视模块380的模式数据,所述模式监视模块380从元数据服务340接收关于关系模式的信息。显示模块382以一种或多种格式将模式显示给用户130。举例来说,嵌套属性的层次可以由缩进等级以列表形式指示。可替代地,可以使用视觉树格式。当模式监视模块380了解到元数据服务340对模式的改变时,模式表示模块378可通过插入新属性、新子属性等来更新模式。举例来说,可将新节点添加到树,包括新中间节点和新叶节点。随着模式的改变,叶节点可转换成中间节点并且属性类型的改变可以用颜色、标记或次级指示来视觉地反映。仅举例来说,次级指示可在光标(当使用例如鼠标或触控板时)悬停在属性之上时显示。当对模式做出改变时,显示模块382可试图将当前显示的模式的中心焦点保持在显示区域的中心。仅举例来说,如果许多新属性被添加到所列出模式的起点,那么先前列出的属性可在屏幕上向下位移或甚至从屏幕移出。为了应对这种视觉上破坏性的改变,显示模块382可滚动属性列表以维持近似恒定的中心位置。到模式的添加元件可视觉地表示,诸如利用描绘轮廓、遮蔽、颜色、字体(加粗、斜体或字型尺寸)。仅举例来说,颜色渐变可指示模式元素近来是如何改变的。仅举例来说,非常亮的蓝色可指示最近改变的模式元素,而颜色蓝色将消退最终达到白色指示已存在持续较长时间段的模式元素。在各种实施中,显示模块382可追踪鼠标移动、键盘使用、在操作系统中的哪些窗口具有焦点以及显示器是否已空白以节省电力,从而确定用户何时聚焦于显示模块382的元素上。举例来说,如果显示模块382确定用户在最近一个小时未与显示模块382交互,那么显示模块382可保持在最近一个小时添加的所有模式元素为亮蓝色。一旦用户再次开始与显示模块382进行交互,颜色蓝色接着就开始消退。以此方式,自从用户最后一次与显示模块382交互对元数据的改变将引起他们的注意,不管他们是否一直在主动地监视显示模块382。用户接口376还包括结果表示模块384,所述结果表示模块384显示一个或多个查询的结果。结果可以文本形式和图形形式的组合来显示,包括表格、图表和图形。视觉表示的类型可由可能够选择访问标记、线性或对数定标以及图表类型的用户进行选择。查询执行器344可以在查询完成之前开始提供结果。当另外的结果可用时,查询执行器344通知结果监视模块386。结果表示模块384接着更新结果的视图并且将那些呈现给显示模块382。在各种其他实施中,结果监视模块386可轮询查询执行器344以确定附加结果何时可用。查询执行器344可在时间进度表上或基于另一个量度(诸如所处理的记录的数量)来提供这些增量结果。当结果监视模块386检测附加结果时,结果表示模块384可能需要调整轴线定标以适应附加数据,可将附加条或片段添加到条形图或饼形图,并且可调整指派给图表元素的值。作为简单化示例,考虑请求针对数据集中的每个等级水平的平均GPA的查询。在查询执行器344处理数据时,初始结果将显示初始记录的平均GPA。当解析附加记录时,可更新GPA。另外,在查询中可能尚未观察到的等级水平将由结果表示模块384添加到结果。在各种应用中,并且针对各种数据集,各种量度(诸如平均值)可在显著数量的记录还没有被解析时开始聚集。这可允许数据趋势的快速可视化,并且可允许用户在等待查询完成之前定制查询或重新制定查询。这对于需要长时间运行(诸如大约数分钟或数小时)的查询来说是特别有价值的。对于一些查询,看到初始结果可向用户指示查询需要重新制定以便返回与那个用户相关的结果。返回到简单化的示例,SQL查询可采取以下形式:“SELECTstudent_id,avg(gpa)FROMstudentsGROUPBYclassORDERBY2DESCENDING;”。查询管理模块388将用户在显示模块382中输入的查询提供至查询执行器344。查询管理模块388可存储先前运行的查询,并且允许这些查询重新运行。另外,查询管理模块388可帮助用户来构造复合查询和/或组合先前查询的结果。在图2E中,高级功能图示出具有多个节点402-1、402-2和402-3(统称为节点402)的存储服务356。尽管示出三个节点402,但可使用更多或更少节点,并且所使用的数量可基于分析框架的需要而动态地变化。节点402的数量可随着需要存储更多数据以及响应于需要附加处理来执行查询和/或提供冗余性而增加。查询执行器344被示出为具有节点406-1、406-2和406-3(统称为节点406)。节点406的数量也可基于查询负荷来动态地变化,并且独立于节点402的数量。在图2F中,存储服务356可提供用于加载到数据仓库192中的数据。元数据服务340可将关系模式提供至数据仓库192,由此数据仓库192可定义表格。数据仓库192可包括除简单存储装置之外的多个功能组件,包括但不限于查询执行器420和ODBC接口424。用户接口376与数据仓库192通信。在各种实施中,用户接口376还可以与图2E的查询执行器344通信。代理348提供ODBC客户端352与查询执行器344之间的接口。查询执行器344与元数据服务340交互,所述元数据服务340存储用于驻存在存储服务356中的数据的模式。过程图3示出用于数据摄取的示例过程。控制在504处开始,在该处可诸如由用户或管理员指明数据源。另外,可选择来自数据源的某些数据集,并且可请求对数据源进行某些取子集和化简操作。控制在508处继续,在该处监视所指明的数据源以查找新数据。在512处,如果已经将新数据对象添加到数据源,那么控制转移到516;否则,控制返回到504,以允许在需要时修改数据源。在516处,推断新对象的模式,这可根据类型函数来执行,诸如图4中所示。在520处,将来自516的所推断出的模式与已经存在的模式合并。所述合并可根据合并函数来执行,诸如图5中所示。在524处,如果需要修饰,那么控制转移到528;否则,控制转移到532。在528处,在数据内识别映射,诸如图8中所示。在536处,如果未识别到新映射,那么控制在532处继续;否则,如果已经识别到新映射,那么控制转移到540。在540处,如果需要映射索引,那么控制转移到544;否则,控制在532处继续。在544处,对于BigIndex或ArrayIndex中的与新映射属性相关联的每个值,将那个值添加到映射索引。另外,如果用户和/或管理员需要,那么针对特定属性,将值添加到值索引。控制接着在532处继续。在各种实施中,在524处的修饰可进行等待,直到处理了第一轮对象为止。举例来说,在初始摄取时,可延迟修饰,直到摄取了所有初始对象为止。以此方式,将已经收集到足够的统计信息来由映射试探法使用。对于附加对象的增量摄取,可在每组新的附加对象之后执行修饰。在532处,如果JSON模式已经由于新对象而改变,那么控制转移到548,在该处将所述模式转换为关系模式。控制在552处继续,在该处对关系视图进行优化,诸如通过展平一对一关系。控制接着在556处继续。如果模式尚未在532处改变,那么控制将直接转移到556。在556处,用新对象的数据填充索引,这可如图7所示来执行。控制接着返回到504。尽管在556处将索引的填充示出为在548处将所推断出的模式转换为关系模式之后执行,但在各种实施中,因为不需要关系模式,所以可在产生关系模式之前填充索引。所述程序可使用所推断出的JSON模式来产生路径和联接键。关系模式充当底层半结构化数据的关系视图。图4示出依赖于递归的类型函数的示例实施。控制在604处开始,在该处如果待定类型的对象是标量,那么控制转移到608。在608处,确定标量的类型,并且在612处返回那个标量类型作为函数的输出。可基于所接收的对象中的自描述来确定标量类型。另外,可使用另外的定类型规则,其可辨认某些字符串表示诸如日期或时间等数据。如果在604处对象不是标量,那么控制转移到616。在616处,如果对象是数组,那么控制转移到620,在该处对数组的每个元素递归地调用类型函数(图4)。在已经接收到这些类型函数的结果时,控制在624处继续,在该处对在620处所确定的元素类型的数组调用诸如图6所示的折叠函数。当由折叠函数返回折叠数组时,在628处由类型函数返回那个折叠数组。如果在616处对象不是数组,那么控制转移到632。在632处,对对象的每个字段递归地调用类型函数(图4)。控制在636处继续,在该处对在632处确定的字段类型的并置调用折叠函数。接着在640处由类型函数返回由折叠函数返回的折叠对象。图5示出将两个模式元素合并为单个模式元素的合并函数的示例实施。合并函数也是递归的,并且在第一次调用时,两个模式元素是先前存在的模式和从新近接收的对象推断出的新模式。在合并函数的进一步递归调用中,模式元素将是这些模式的子元素。控制在704处开始,在该处如果待合并的模式元素是等效的,那么控制转移到708并且返回所述等效模式元素中的任一个。否则,控制转移到712,在该处如果待合并的模式元素均为数组,那么控制转移到716;否则,控制转移到720。在716处,如果待合并的数组之一是空的,那么在724处返回另一个数组。否则,控制在728处继续,在该处对含有两个待合并的数组的元素的数组调用诸如图6中所示的折叠函数。接着在732处由合并函数返回由折叠函数返回的折叠数组。在720处,如果待合并的模式元素之一是空的,那么在736处由合并函数返回另一个模式元素。如果待合并的模式元素都不是空的,那么控制在740处继续,在该处对含有两个待合并的模式元素的键-值对的对象调用折叠函数。接着在744处由合并函数返回由折叠函数返回的折叠对象。图6示出折叠函数的示例实施。控制在804处开始,在该处如果待折叠的对象是数组,那么控制转移到808;否则,控制转移到812。在808处,如果数组含有均为数组的一对值,那么控制转移到816;否则,控制在820处继续。在820处,如果数组含有均为对象的一对值,那么控制转移到816;否则,控制在824处继续。在824处,如果数组含有为相等标量类型的一对值,那么控制转移到816;否则,完成折叠并且从折叠函数返回数组。在816处,对由808、820或824识别的该对值调用诸如图5中所示的合并函数。控制在828处继续,在该处用由合并函数返回的单个值替换该对值。在812处,如果对象中的任何键都是相同的,那么控制转移到832;否则,折叠完成并且返回对象。在832处,控制选择相同的一对键并且在836中继续。如果该对键的值均为数组或均为对象,那么控制转移到840;否则,控制转移到844。在840处,对该对键的值调用合并函数。控制在848处继续,在该处用具有由合并函数返回的值的单个键替换该对键。控制接着在852处继续,在该处如果任何附加键是相同的,那么控制转移到832;否则,折叠完成并且返回所修改的对象。在844处,如果该对键的值均为标量,那么控制转移到856;否则,控制转移到852。在856处,如果该对键的值的标量类型是相等的,那么控制转移到840来合并那几对键;否则,控制转移到852。图7示出用于用来自新近检索到的对象的数据填充索引的示例过程。控制在904处开始,在该处如果需要RowIndex,那么控制转移到908;否则,控制转移到912。在908处,如上所述将对象添加到RowIndex,并且控制在912处继续。在912处,将对象展平为用于当前关系模式的关系元组,并且根据需要创建联接键。控制在916处继续,在该处控制确定是否存在待添加到索引的更多元组。如果是,那么控制转移到920;否则,索引已经被填充,并且因而控制结束。在920处,控制确定元组是否用于数组表格。如果是,那么控制转移到924;否则,控制转移到928。在924处,如果在数组表格中存在更多值列,那么控制转移到932。在932处,如果列值存在于原始检索对象中,那么在936处将值添加到ArrayIndex。控制接着在940处继续。如果针对所述列需要ValueIndex,那么控制转移到944;否则,控制返回到924。如果在932处列值不存在于原始检索对象中,那么控制返回到924。在928处,如果元组用于映射表格,那么控制转移到948;否则,控制转移到952。在948处,控制确定是否更多值列保留在映射表格中。如果是,那么控制转移到956;否则,控制返回到916。在956处,控制确定列值是否存在于原始检索对象中。如果是,那么控制转移到960;否则,控制返回到948。在960处,将值添加到MapIndex,并且控制转移到964。在964处,如果针对所述列需要ValueIndex,那么在968中将值添加到ValueIndex;在任一情况下,控制接着返回到948。在952处,控制确定是否更多列存在于表格中。如果是,那么控制转移到972;否则,控制返回到916。在972处,控制确定列值是否存在于原始检索对象中。如果是,那么控制转移到976;否则,控制返回到952。在976处,将值添加到BigIndex并且控制在980处继续。在980处,如果针对所述列需要ValueIndex,那么控制转移到984,在该处将值添加到ValueIndex;在任一情况下,控制接着返回到952。图8示出用于识别映射的示例过程。控制在1004处开始,在该处选择第一个对象。控制在1008处继续,在该处如果对象是空的,那么在1012处将包含对象指明为映射;否则,控制转移到1016。在1016处,控制如上所述确定平均字段频率与包含对象的频率的比率。控制在1020处继续,在该处如果比率低于阈值,那么控制转移到1012来将包含对象指明为映射;否则,控制转移到1024。仅举例来说,阈值可为用户可调整的,和/或可基于所观测的数据为动态的。在各种实施中,随着关系模式增大,可调整试探法来更容易地将字段识别为映射。在1012处,将包含对象指明为映射,并且控制在1024处继续。如果有更多对象要评估,那么控制转移到1028,在该处选择下一个对象,并且控制在1008处继续;否则,控制结束。图9示出依赖于递归来创建关系模式的create_schema函数的示例实施。在调用create_schema函数时,控制将模式元素(Schema_Element)并入到表格(Current_Table)中。为此,控制在1104处开始,在该处如果Schema_Element是对象,那么控制转移到1108;否则,控制转移到1112。在1108处,如果对象是空对象,那么将对象视为映射并且控制转移到1116;否则,控制在1120处继续。在1120处,针对嵌套对象创建新表格(New_Table)。在1124处,将联接键(Join_Key)添加到Current_Table,并且在1128处,将对应的Join_Key添加到New_Table。控制接着在1132处继续,在该处针对嵌套对象中的每个字段,递归地调用create_schema函数来向表格添加字段。控制接着在1136处从create_schema函数的当前调用返回。在1112处,如果Schema_Element是映射,那么控制转移到1116;否则,控制转移到1138。在1116处,针对映射创建新表格(New_Table)。控制在1140处继续,在该处将Join_Key添加到Current_Table,并且在1144处,将对应的Join_Key添加到New_Table。在1148处,将具有字符串类型的键字段添加到New_Table。控制在1152处继续,在该处针对映射中的每个值类型,递归地调用create_schema函数来将值类型添加到New_Table。控制接着在1136返回。在1138处,控制确定Schema_Element是否是数组。如果是,那么控制转移到1156;否则,控制转移到1160。在1156处,针对数组创建新表格(New_Table),在1164处将Join_Key添加到Current_Table,并且在1168处将对应的Join_Key添加到New_Table。在1172处,将具有整数类型的索引字段添加到New_Table。控制在1176处继续,在该处针对数组中的每个项目类型,调用create_schema函数来将项目类型添加到New_Table。控制接着在1136返回。在1160处,通过消元过程,Schema_Element是基元。如果在Current_Table中已经存在具有与基元相同的名称的字段,那么控制转移到1180;否则,控制转移到1184。在1184处,简单地将名称字段添加到Current_Table,并且控制在1136处返回。在1180处,存在类型多态性,并且因此重命名Current_Table中的具有与基元相同的名称的现有字段以将其类型附加到字段名称。控制在1188处继续,在该处基于当前基元来添加新字段,其中类型附加到字段名称。控制接着在1136处返回。在图10A中,控制在1204处开始,在该处用户或管理员指明和/或修改数据源。在1208处,控制从数据推断出模式并且将索引填充为所推断出的模式,如以上详细描述的。在1212处,控制确定是否需要修饰,所述修饰可由用户或管理员来配置。如果是,那么控制转移到1216;否则,控制转移到1220。在1216处,控制识别模式内的映射并且更新模式以反映所识别的映射。基于来自用户和/或管理员的设置,可手动恢复某些所识别的映射以便由用户和/或管理员来将列分离。这可以在摄取时或在使用数据期间的任何时间执行。一旦识别出映射并且创建了映射索引,数据就可保持在映射索引中,以使得模式可反映映射或单独反映列,并且用户或管理员可在这些配置之间切换而无需重新加载数据。控制在1220处继续。在1220处,控制将所推断的模式转换为关系模式。在1224处,控制将数据封装成特定数据仓库在使用中可辨认的格式。在1228处,在数据仓库中创建根据关系模式的表格。仅举例来说,可以使用SQL创建表格命令。在1232处,将封装的数据批量加载到数据仓库中。当数据仓库能够并行地进行批量加载时,在1224处的数据封装可针对每个数据库关系创建多个文件以加速1232的批量加载。在图10B中,当索引存储区不可用、太满或在当前时间针对这个特定时间不需要时,可以使用修改的过程。在1204之后,在1250处,推断数据的模式。不同于图10A,数据不用于填充索引。在1220之后,在1228处,在数据仓库中创建根据关系模式的表格。控制在1254处继续,在该处对数据执行第二遍以创建用于本地加载到数据仓库中的中间文件。控制接着在1232处继续,在该处批量加载变换到数据仓库。在图11中,示出用于将新数据整合到数据仓库支持的分析平台中的示例过程。在1304处,控制确定是否已从所指明的数据源接收到新数据。如果是,那么控制转移到1308;否则,控制保持在1304中。在1308处,控制推断新数据的模式并且利用新数据填充索引。控制在1312处继续,在该处控制确定新数据的模式是否是已存在模式的子集。如果是,那么控制在1316处继续;否则,控制转移到1320。在1320,新模式与现有模式合并并且控制在1324处继续。在1324处,控制确定是否需要修饰,且如果是,那么控制转移到1328;否则,控制转移到1332。在1328处,控制基于新数据来识别映射。在新数据已导致根据映射标准具有映射的资格的属性的情况下,这些所识别的映射可包含新数据以及先前数据。如果识别出附加映射,那么更新模式。控制接着在1332处继续。在1332处,将合并的模式转换为关系模式。在1336处,在数据仓库中修改表格和/或创建新表格。在1340处,通知用户接口模式已更新以及用户接口因此应向用户显示更新的模式。控制接着在1316处继续。在1316处,控制将来自索引的用于批量加载的新数据封装。控制在1344处继续,在该处执行将新封装的数据批量加载到数据仓库中。控制接着返回到1304。在图12中,执行用户接口操作的示例高级概述。控制在1404处开始,在该处将推断出的关系模式呈现给用户。控制在1408处继续,在该处如果模式已改变,那么控制转移到1412;否则,控制转移到1416。在1412处,控制在用户接口中更新所显示的模式并且在1420处继续。在1420处,控制任选地以图形方式识别对模式的改变。仅举例来说,可视觉上强调最近改变的模式元素。在各种实施中,用户接口可基于最后一次查询何时运行来确定模式元素最近是否发生改变。仅举例来说,可特别强调自从最后一次运行查询已改变的模式元素。控制接着在1416处继续。在1416处,如果用户已请求新查询,那么控制转移到1424;否则,控制转移到1428。在1424处,控制开始显示来自所执行的查询的查询结果。这些结果可以是不完整的,包括缺少某些行或列和/或具有不准确的或部分不准确的数据。控制在1428处继续。在1428处,如果存在来自正在进行的查询的附加查询结果,那么控制转移到1432;否则,控制返回到1408。在1432处,控制利用附加结果来更新接口。控制在1436处继续,在该处如果正在显示数据曲线,那么可修改图表的各方面,诸如可执行重新定标和重新标注轴线。控制在1440处继续,在该处控制以图形方式识别对查询结果的改变。仅举例来说,强调反复改变的查询结果。在各种实施中,可更显著地强调已改变了较大比例或较大量的查询结果。另外,可唯一地识别新列和/或新行。此外,重影和/或着色可指示当前值和先前显示的值以提供用于查询结果中的趋势的视觉参考。控制接着返回到1408。图形用户接口在图13A中,图形用户接口在左侧窗格中显示推断出的模式,而在右侧窗格中示出查询和查询结果。在这些示例中,呈现推特属性的示例表示。在图13B中,请注意,自从图13A已出现附加的关系模式属性。具体地说,以in_reply_to开始的属性已基于被解析的附加数据(其包括那些属性)而动态地添加到用户接口。在图13C中,以展开形式示出嵌套对象的一个表示。具体地说,示出在节点用户下面的属性。在图13D中,呈现数据的表格式表示。在这个显示中,查询已找到10种语言。在图13E中,现已找到24种语言。在这个特定示例中,用于原始10种语言的计数还未改变,从而指示在图13D的显示与图13E的显示之间解析的记录是图13D的初始10种中未示出的附加语言。在图13B中,将附加属性动态地添加到在图13A中所示的显示之后的显示。在图13E中,将附加查询结果动态地添加到在图13D中所示的显示之后的显示。自动提取、变换、加载(ETL)以上,介绍了模式推断,模式推断从半结构化对象(在某些实施中,JSON文档)的集合中提取累积(或全局)模式(在某些实施中,也称为JSON模式)。当更多的输入变得可用时,这种累积模式增量地进行更新。可修饰累积模式以指明属于映射或数组的实体集。创建这种累积模式并且基于所述累积模式来处理数据可有利地用作传统的提取、变换、加载(ETL)过程的一部分或代替其使用。所得的ETL过程可辨认速度、保真度或可用性中的一个或多个的改善。一般来说,ETL指的是控制数据从一个或多个源位置到一个或多个目的地位置的移动的过程,其中具有所选择数据集经历某些变换的任选变换阶段。变换可能还需要遵从目的地之一的输入格式。源和目的地可以是关系数据库、对象存储区(诸如NoSQL或键-值存储区)或遵循那些数据库或存储区的格式的数据存储库(诸如存储含有CSV或JSON数据的文件或文档的本地或分布式文件系统或云存储区)。ETL保真度可定义为数据项目从源映射到目的地的准确度。举例来说,被分派任务用于将来自源的数据项目a、b和c加载到目的地中并且导致项目b和c驻留在目的地中的ETL过程比仅导致项目c被加载的ETL过程具有更好的保真度。ETL可用性可以用户和计算系统在目的地计算系统上执行任务时所采取的(减少的)步骤数量来测量,所述目的地计算系统使用所加载数据的部分作为输入。举例来说,均导致从源加载到目的地中的数据项目b和c的两个不同ETL过程可具有不同的可用性,条件是一个ETL过程在计算目的地系统上的两个项目中的最大者时导致较小数量的步骤。如上所述,半结构化数据可变换为关系形式并且被加载到支持带索引的列式存储装置的系统中。除了或代替列式存储装置,数据可被加载到多个目标中。这可一般化为描述灵活的ETL过程,所述ETL过程从一个或多个(可能的半结构化)源获取数据,任选地将施加一个或多个变换,并且将数据加载到一个或多个(可能的关系)目标中。在各种实施中,ETL过程可使用针对中间存储装置的索引存储区或可省略中间存储区。图14示出ETL过程的概述,并且为图2B的更高级和更一般化版本。在图14的左侧,数据从一个或多个数据源(诸如数据源1504和1508)中出来并且由数据收集器模块1512以原始记录的形式提取。数据收集器模块1512可产生呈半结构化格式诸如JSON的原始记录。当数据源1504和1508含有呈预定格式的数据,诸如存储JSON对象的文本文件,数据收集器模块1512可使JSON对象通过而不改变。在各种实施中,可实施一个或多个附加数据收集器模块(未示出)来并行地处理来自同一个数据源或多个数据源的数据。另外,可一连串地实施数据收集器模块以便渐进地将数据转换为模式推断和统计信息收集模块1516和元数据存储区1540可用的形式。所收集的记录被传递到模式推断和统计信息收集模块1516。基于由模式推断和统计信息收集模块1516确定的累积模式,可将数据加载到索引存储区1520以便稍后加载到一个或多个目的地系统(如图14所示,数据目的地系统1524和1528)中。另外或作为替代,数据可绕过索引存储区324并且借助于导出模块1534直接被发送到数据目的地系统1524或1528中的一个或多个。在通过导出模块1534将来自索引存储区1520的数据存储到数据目的地系统1524或1528中的一个或多个中之前,可实施变换模块1536对所述数据执行一个或多个变换。作为替代,变换模块1536可对绕过索引存储区从模式推断和统计信息收集模块1516直接接收的数据执行变换。导出模块1534将数据以与数据目的地系统1524和1528的摄取命令兼容的格式提供给它们。仅举例来说,导出模块1534可向基于SQL的数据仓库或数据库提供呈表格式行形式的数据。导出模块1534可响应于数据目的地系统1524接受JSON对象而将对象诸如JSON对象提供至数据目的地系统1524。在各种实施中,对象可从数据收集器模块1512通过而不改变。响应于数据目的地系统1524接受列式数据,导出模块1534可使基于列的数据从索引存储区1520通过而不改变。元数据存储区1540记录数据收集器模块1512、模式推断和统计信息收集模块1516以及索引存储区1520中的每一个的状态。调度模块1544将工作指派给数据收集器模块1512、模式推断和统计信息收集模块1516、索引存储区1520以及导出模块1534。调度模块1544可基于以下参照图16A-图16B更详细地描述的关联性而调度工作。如以下描述的监视系统1548记录关于数据收集器模块1512、模式推断和统计信息收集模块1516、索引存储区1520、变换模块1536、元数据存储区1540以及数据目的地系统中的一个或多个(在图14的示例中,数据目的地系统1524)的操作的性能和错误数据。从多个源提取数据数据源对象源现将输入源的定义扩展到ETL过程以覆盖对象源。这些源可包括NoSQL存储区、文档存储区(诸如MongoDB和Couchbase)、数据结构存储区(诸如Redis)以及键/多值存储区(诸如Cassandra、HBase和DynamoDB)。可将存储在文件存储区上的文件内的对象处理为附加的对象源。存储在文件中的对象可包括JSON、BSON、Protobuf、Avro、Thrift和XML。在各种实施中,可自动检测选择用于数据提取的一些或所有输入源的性质。专用的收集器可用于不同类型的输入源。为简单起见,余下讨论将使用JSON文档作为对象源的示例。本公开可替代地使用另一种类型的对象源,并且另一个对象源与JSON之间可存在一对一映射。换句话说,本公开直接适用于那些其他类型的对象源。关系源关系源诸如数据库也可用作源。从关系源提取数据的过程在一些方式上可被视为反向地运行从JSON模式产生关系模式的过程。所述过程开始于从其中识别每个行将转换为对象的根表格。根表格可由用户指定,自动地由数据收集器过程自动选择,或者由数据收集器过程基于先前的试探法或由用户或管理员提供的规则集来选择。数据收集器可选择经受稍后由用户进行的手动改变的根表格。那个根表格的行与其他表格的行结合以创建完整的对象。举例来说,可使用外来键关系、统计配对或用户指导来选择其他表格中的行。可通过使用统计信息检测两个列之间的值分布的相似度来实施统计配对。具体地说,时间戳和键列是用于可预测关系的列的良好候选物。如果父表格和其子表格的行之间存在一对一关系,那么子表格中的行简单地变成主要对象中的嵌套对象。如果存在一对多关系,那么行变成嵌套对象阵列的一部分。这个过程可创建可映射到JSON文档的对象,此时直接应用本公开中对JSON处理的描述。举例来说,考虑以下两个表格:表格:用户用户id、姓名、年龄1,"Nate",272,"Stavros",87表格:地址用户id,开始,结束,城市1,1995,2006,AnnArbor1,2006,空值,RedwoodCity2,2005,2007,Cambridge2,2007,空值,SanFrancisco可从那些表格中推断出JSON模式如下:user:{"用户id":"integer","姓名":"string","年龄":"integer","地址":[{"开始":"integer","结束":"integer","城市":"string"}]}使用来自输入表格的JSON模式来创建对象引出以下对象:{"用户id":1,"姓名":"Nate","年龄":27,"地址":[{"开始":1995,"结束":2006","城市":“AnnArbor"},{"开始":2006,"结束":空值,"城市":"RedwoodCity"}]}{"用户id":2,"姓名":"Stavros","年龄":87,"地址":[{"开始":2005,"结束":2007","城市":"Cambridge"},{"开始":2007,"结束":空值,"城市":"SanFrancisco"}]}通过事件化支持关系源在某些情况下,关系源可含有与单个根表格不相关联的多个表格或者将不同表格结合在一起的方式可能不明显。在每个表格(或表格集)包括具有时间戳数据的至少一个列的情况下,收集器过程可使表格集“事件化”(被称为“事件化”)如下。创建新的逻辑或物理事件表格,其具有来自输入表格的所有列的联合作为列(多于一个表格中出现的相同的列名称可导向新表格中的具有那个名称的仅一个列)和至少两个新列:“事件”和“时间”。这些名称可在事件化时以编程方式更改(诸如利用预定义的前缀和/或后缀)以避免与现有表格的列的名称冲突。利用来自输入表格集中的每个表格的行来填充新表格。对于新表格中的导出行中不存在的列,可以使用空值。“事件”列将从其中导出行的输入表格的名称当作值。“时间”列指定事件化表格的排序次序。利用来自输入表格的对应行的时间戳信息来填充“时间”列。当存在具有源表格中的时间戳数据的多个列时,可添加多个“时间”列,诸如“时间1”、“时间2”等。每个“时间”列由输入表格的对应时间戳列来填充。作为替代,输入表格中的具有时间戳数据的列中的一个可被选择作为控制列并且用于使表格事件化。对输入表格中的时间戳列的选择可通过自动规则(例如,总是捡取最小的值或总是捡取最左侧的列)、基于用户输入或通过统计规则来完成,所述统计规则可有助于推导出由行表示的事件最可能发生的时间。作为事件化的示例,考虑以下三个示例源表格的模式:table:user_log{″id″:″number″,″session_start″:″timestamp″,″session_end″:″timestamp″}table:query_log{″id″:″number″,″query_text″:″string″,″query_start″:″timestamp″,″duration″:″number″}table:cpu_load{″time″:″timestamp″,″load″:″float″}用于事件化表格的示例模式在此处示出:考虑来自源表格中的每一个的一个示例行:user_log:(15213,″01/01/201412:15:00″,″01/01/201412:15:30″)query_log:(79004525,″select*fromT;″,″01/01/201410:10:00″,53)cpu_load:(″01/01/201411:20:30″,74.5)以下是如何填充事件化表格的示例:(user_log″,″01/01/201412:15:00″,″01/01/201412:15:30″,15213,″01/01/201412:15:00″,″01/01/201412:15:30″,NULL,NULL,NULL,NULL,NULL),(″query_log″,″01/01/201410:10:00″,NULL,79004525,NULL,NULL,″select*fromT;″,″01/01/201410:10:00″,53,NULL,NULL),(″cpu_load″,″01/01/201411:20:30″,NULL,NULL,NULL,NULL,NULL,NULL,NULL,″01/01/201411:20:30″,74.5)请注意,事件化表格根据时间戳值在模式中的原始位置来保持所述时间戳值,而且还将一个或多个(在这种情况下,多达两个)时间戳复制到特殊的“时间”列中以使行事件化。以此方式,输入的不同行可包括手动排除的时间戳列,所述时间戳列在仍然创建单个参考“时间”列的同时被保存。在源输入处的输入表格集的事件化可作为物理表格(所述表格被物化)或作为逻辑表格而存在。对于逻辑表格,事件化过程可创建属于事件化表格的行流并且这个流式输入被导向到ETL过程。事件化允许将关系源作为对象源进行处理,因为事件化表格中的每个行类似于含有关于在某个时间发生的事件的信息的对象存储区中的对象。事件化可导致增加的可用性,特别是在用户想要查询不同事件中的关于提取信息的目的地点的数据。举例来说,查询关系源以查找关于具有某个时间戳值(或值范围)的行的信息可能是比查询事件化表格更复杂且更耗时的查询。数据收集器收集器是可用于从上述数据源中的一个或多个提取单独记录的软件组件。尽管以上描述了以标准格式(JSON、BSON等,其可以是或可以不是压缩的)处理所接收的文件,但可以使用其他机制来监视用于新数据的数据源并且提取这个数据以便发送到摄取过程。文件系统监视如果数据被提供在文件系统中的一个或多个目录中,那么收集器过程可周期性地监视文件系统以发现变化。文件系统可以是传统的本地文件系统(例如,ext4)或具有文件系统式接口(例如,HDFS、AmazonS3)的分布式存储区。根据文件系统的精确接口,收集器可通过周期性地扫描文件系统并且与现有文件列表进行比较、或使用建立到接口中的通知机制(例如,S3桶日志)来检测新文件。周期性快照如果源数据存储在现有数据存储区中而不是存储在文件系统诸如关系数据库(例如MySQL、PostgreSQL、Oracle等)或NoSQL存储区(例如MongoDB、CouchDB等)中,那么收集器可利用内建的快照机制。大多数数据存储区支持用于将数据导出到文件系统或另一个过程的机制。举例来说,PostgreSQL支持SQLCOPY命令并且被称为pg_dump外部功用是可用的。利用这个机制,可周期性地执行源数据的转储以摄取新记录。可由收集器通过远程过程调用或由用户启动快照。当获取了完整的快照时,可在多个快照上出现单独记录。此类重复记录可被识别出并且忽略,诸如通过使用源特定主键或在保证完整记录是不同的情况下出于比较目的对整个记录使用散列函数。复制日志支持复制的许多数据存储区维持用于确保副本保持同步的操作日志。如果可从外部访问这个日志,那么收集器可直接使用日志来查找新数据。举例来说,MongoDB暴露oplog(操作日志),其可使用标准MongoDBAPI进行查询,并且含有用于数据库中每个插入、更新和删除操作的条目。通过读取该日志,监视过程可识别需要摄取的新记录。提取数据一旦已检测到新源数据,存在将那个数据发送到摄取过程的若干方式。如果数据已经在文件中,那么摄取过程可简单地打开文件并且直接读取数据。如果文件位于网络中,那么可在使用网络文件系统如HDFS(Hadoop分布式文件系统)的情况下通过网络远程地打开文件。如果数据尚未在文件系统中(例如,其来自复制日志),那么收集器可创建含有新记录的一个或多个中间文件。这些文件可存储在传统文件系统或诸如HDFS或AmazonS3的分布式存储区中。一旦创建了文件,就可如上所述那样加载它们。对于收集器还可能的是,使用IPC(进程间通信)或RPC(远程过程调用)机制直接将数据发送到摄取过程。这使得摄取过程开始处理新数据而无需等待其被写入文件,并且避免维持单独的数据副本。在期望具有数据备份的情况下(例如,当源仅能够访问一次时),可将数据直接发送到摄取过程并且异步写入备份文件。这个备份可用于在摄取过程中出现错误的情况下进行恢复。统计信息因为模式推断步骤需要处理所有源数据,所以可在这个过程中计算统计信息而无需附加通过数据。统计信息可提供多种益处,包括增强ETL保真度。关于模式属性的统计信息第一类统计信息可从来自源数据中的累积模式的各个属性计算出。首先,可跟踪每个属性和类型在数据中出现的频率。由于多种原因这可以是有用的。举例来说,如上所述,用于映射修饰的试探法是基于属性相对于含有所述属性的对象的频率的出现的频率。频率还可用于基于类型做出决策以及解决类型冲突。类型信息可用于优化物理存储决策。举例来说,可跟踪数字类型并且使用它来区分32位整数和64位整数以及浮点类型。这些类型中的每一种可能需要不同的存储空间量,因此确定哪种类型适用允许配置最小的必需空间。类型多态性发生在同一属性在具有不同类型的源数据中出现多次时。以上所述的模式推断机制和索引存储区完全支持类型多态性,但在一些情况下,某个字段的多态性可能是不合乎期望的。举例来说,如果单个属性表现为整数占记录的99.9%且字符串占另外0.1%,那么字符串型记录可能是寄生的。举例来说,字符串型记录可指示数据条目或校验中的错误或源数据中的损坏。这些异常记录可吸引用户的注意力和/或可基于试探法而自动改写。举例来说,如果少于1%的记录是相异类型,那么这些记录可被改写为主导类型,并且可为ETL过程创建日志条目以标记这个事件并且任选地描绘改写的源数据。考虑以下示例JSON记录:{″id″:12345678,″location″:Saratoga,CA″,″tags″:{″urgent″,″direct″]}{″id″:″12345678″,″location″:″SanFrancisco,CA″,″source″:″iPhone″}从这些记录推断出的累积模式可以是:累积模式可包装在JSON模式中,所述JSON模式将累积模式的每种属性和类型与计数相关联。例如:请注意,自从id一次表现为字符串并且一次表现为32位整数,每种类型以计数一列出,而根对象具有计数二。此外,tags数组仅出现一次,因此它具有计数一,但它含有两个字符串项目,因此项目字段具有计数二。可在定类型过程中计算记录的每种属性的频率,并且可简单地添加来自多种属性的计数。因为加法是相关联的且可交换的,所以这个过程可以并行地完成。计数可独立地维持在单独的数据流上并且随后合并来计算全局统计信息。其他统计信息可以相同的方式与每种属性相关联,只要它们能够以可交换的且相关联的方式计算。举例来说,可跟踪统计信息诸如字符串属性的平均长度、或字符串值出现以表示另一种类型的频率(诸如日期)。对于平均值,单独地维持总和和计数,并且一旦合计了所有数据就执行除法(因为除法不是相关联的或可交换的)。关于值的统计信息除了收集关于源数据的模式的统计信息(例如每个键出现的频率)之外,可编译关于与特定属性相关联的值的统计信息。这些统计信息可用于多种应用,包括查询优化、数据发现和异常检测。受关注的统计信息取决于属性的类型。对于数字属性,这些量度可包括基本统计测量值,诸如分布的最小值和最大值、以及平均值和标准偏差。为了允许并行化,可选择统计信息以使得可使用可交换的且相关联的操作来收集它们。可根据需要维持关于标量值的更复杂的统计信息,包括分布的直方图。在可接受一定量的错误的情形下,可以使用计算起来更便宜的近似算法。举例来说,可以使用HyperLogLog算法来计算列的近似基数(不同值的数量),并且可以使用Q-Digest算法来计算近似分位数。可以与计算关于特性的统计信息相同的方式来计算关于值的统计信息。在类型推断期间,对每个值进行分析以确定其类型,并且可同时编译统计信息。逻辑统计信息可维持在存储器中并且随后与全局统计信息合并并且与模式一起存储在元数据存储区中。维持大量状态的统计信息可任选地存储在不同存储区诸如索引存储区或专用统计信息存储区中,以便改善存取性能。关于整个记录的统计信息一些统计信息是基于多种属性而不是单个属性或值。一个常见示例是识别哪些列经常一起出现。举例来说,基于日志数据的源可组合同一个流中的不同类型的记录。以下JSON记录是一个示例:{″user″:″mashah″,″err_num″:4,″err_msg″:″Connectionerror.″}{″user″:″lstavrachi″,″session_time″:23,″OS″:″MacOSX″}{″user″:″mashah″,″session_time″:17,″OS″:″Windows7″}{″operation″:″update″,″duration″:10,″frequency″:3600}第一记录表示用户错误,接下来两个表示用户会话,并且第四个表示系统操作。尽管根据这些记录确定累积模式以及将累积模式转换为关系模式将会使这些记录组合成同一个关系表格,但当这些记录描述相异事件时他们可以逻辑地分开。分析记录群组之间的区别的一种方式是存储邻接矩阵,其中每个条目表示一对列并且含有两个列出现在同一个记录中的次数。邻接矩阵可以是上或下三角矩阵,因为列的次序是不相关的。在以上示例中,针对user行、session_time列的条目(等效地,user列、session_time行)将含有2,因为这些属性均出现在两个记录中,而用于user行和operation列的条目将含有0,因为这些属性在数据集中不同现。邻接矩阵可以多种格式(诸如邻近表)存储,并且可在解析记录处于存储器中时进行更新。可通过计算对应条目的总和来合并多个矩阵,因此可并行地对它们进行计算。矩阵随着列的数量的平方增长,但如果矩阵是稀疏的则可将其以压缩格式存储,从而使用大大减少的空间。正如其他统计信息,矩阵可存储在元数据存储区或索引存储区中。一旦计算出邻接矩阵,就可以若干方式使用它来识别相关的列。矩阵对应于加权图形,在所述加权图形中节点是属性,并且如果对应于其端点的列一起出现i次则边以加权i出现。这个图形中的团表示列集合,其中每个列与每隔一个列一起出现。上述示例包括以下团:(″user″,″err_num″,″err_msg″)(″user″,″session_time″,″OS″)(″operation″,″duration″,″frequency″)这些有利地对应于三个单独事件类型并且可呈现给用户或用于自动数据变换。可使用标准图形算法来计算这些团,并且所述算法可被配置成需要团中的每个边以便具有至少最小的加权。为了捕获相关列的更广泛视图,可将上述图形中的所有连接的成分分组。换句话说,其间存在路径的任何两个属性可组合成一个分组。以上示例将产生两个分组:(″user″,″err_num″,″err_msg″,″session_time″,″OS″)(″operation″,″duration″,″frequency″)请注意,err_num和os在同一个连接的成分而不是同一个团中出现,这是因为错误记录和会话记录均具有user字段。相关列的这种较宽松概念可用于将大的不相关数据集粗略地分开。以上所述的邻接矩阵仅基于每个记录的模式,但可能期望使某些值与列的存在与否相关联。不相关记录具有不同模式的一种情况是当(例如)每个记录包括标识记录的类型的明确属性(诸如event_id)时。在以上示例中,用户错误可具有为1的event_id,用户会话可具有为2的event_id,并且系统操作可具有为3的event_id。如果可确定(或由用户指示)event_id的重要性,那么可使用event_id通过事件类型来隔离属性。在这种情况下,可通过将所有记录的模式与那个event_id值合并来维持用于每个event_id的单独累积模式。通过event_id拆分数据源的过程被称为“分解(shredding)”并且将在下文进一步讨论。使用索引存储区的异步统计信息尽管以上统计信息通常可并行地计算,但一些统计信息在所有数据并不一次到位(例如,中值和众数)的情况下难以计算。这些统计信息可在已使用索引存储区的查询功能性加载数据之后进行计算。因为这可能需要扫描大量的数据,所以这可异步地并且在索引存储区另外闲置的时间期间执行。错误统计信息可值得记录的另一类统计信息是错误统计信息。存在多种不同类型的错误,这些错误可能是数据本身遇到的或摄取期间系统操作遇到的。举例来说,这些错误可包括解压缩输入数据错误、输入文件格式错误、特定记录解析错误、字符串编码(例如UTF-8)错误、试图打开锁定文件的错误以及通过网络访问源数据的错误。可将关于这些统计的信息维持在元数据存储区中并且根据需要发送给用户和/或管理员。索引存储区中的中间存储装置可将所摄取的数据存储在有利于存储和查询的索引的集合中,所述索引的集合可包括以上描述的BigIndex(BI)、ArrayIndex(AI)和RowIndex(RI)。用户可直接查询索引存储区,但其在加载另一个系统的过程中也可用作中间存储区。本章节描述索引存储区作为用于ETL过程的中间存储区的使用。批量导出当使用索引存储区作为用于ETL的中间存储区域时,从索引存储区有效地导出批量数据是个问题。例如,当使用硬盘驱动器(具体地,磁驱动器)时,更有效地顺序地读取大的数据块,从而避免搜寻等待时间并且因此实现最大带宽。对于顺序地访问介质如硬盘驱动器,可确定给定的峰值性能部分(f)。在给定磁盘的搜寻等待时间(L)和持续的顺序带宽(B)的情况下,每次搜寻必须读取以实现所期望的峰值性能部分的字节数量(N)可计算如下:N=(f/(1-f))*L*B举例来说,考虑具有持续的100MB/s带宽和10ms的平均每次搜寻(seek)等待时间的磁盘。为了实现90%的峰值性能(f=.9):N=(.9/(1-.9))*10ms/seek*100MB/SN=9MB/seek因此,实现指定部分的性能的目标在于以至少9MB的顺序突发来读取数据。当数据的目标是基于磁盘的系统时,基于目标的写入性能来应用相同的公式。在概念上,从索引存储区导出数据可以行或以列为单位执行。模式选择取决于目的地数据存储区的能力。当导出列时,可导出来自BI、AI或MI的数据的大分类范围(这些范围中的每一个可首先由列分类,然后由元组ID分类)。一旦所请求的元组被分类,针对每一列应读取至少9MB的元组。为了提高效率,可在将来自一个列的所有元组移动到下一列之前读取所有元组并将其写入到输出。当导出行时,存在至少两个选项。如果RI可用,那么可通过元组ID将所请求的数据存储在RI中,并且随后以分类次序读取。由于RI也是以分类次序存储的,这将顺序地访问磁盘。行随后需要适当地格式化以用于输出系统。当RI不用于导出时,行可由例如BI、AI和MI构造。为提高效率,一次从BI、AI和MI的每一列读取大的数据块。为了生成输出行,将在可生成任何行之前从针对给定行的每个输出列中读取数据。在具有足够的RAM的情况下,可将每一列的N兆字节数据块读取到RAM中,且然后可输出行。如果列被压缩,那么可将列尽可能地保持压缩以便节省存储器。另外,随着数据被写出,可实时地释放存储器。一个列的N兆字节数据块与另一个列的N兆字节数据块可能将不具有相同数量的元组(尤其是在使用压缩时)。因此,针对每一列的数据块可能需要独立地获取,因为一个列的元组将在另一个列的元组之前用尽。为了使磁盘等待时间最小化,可采用预获取,但预获取和部分解压缩均可增加存储器转换要求。用于从BI、AI和MI批量导出行的示例伪代码:创建每列的高速缓存,这个高速缓存利用面向流传输的替换策略缓存用于tid的数据并且实施预获取。foroutput_tuple_ids中的tid:开始建立新元组For这个元组的每列:查找高速缓存中的tidiftid存在逐出tid以针对流传输进行优化检查这个高速缓存中的自由空间,if有足够自由空间,预获取下一块,iftid不存在,从AI获取含有tid的数据块,if必要,解压缩含有数据的数据块将数据添加到元组将元组添加到输出缓冲器if输出缓冲器是满的,将输出发送到目的地如果系统具有有限的RAM,那么转换可通过多遍完成,其中每一遍读取尽可能多的列数据块并且产生存储在磁盘上的部分行输出数据块。随后可如同列那样对部分行输出数据块进行处理并且可重复所述过程直到输出完整的行。例如,参见图15,其中示出包括列A、B、C和D的索引的非易失性存储装置1580(诸如在硬盘驱动器上)的示例布置。为了导出行,需要来自每一列A、B、C和D的数据。代替读取来自非易失性存储装置1580中的每一列的单个列值(这可能由于搜寻和存取时间而施加显著惩罚),可将每一列的数据块读取到存储器中。在这个简化的说明中,在非易失性存储装置1580中的每一列中存在1024个条目。存储器1584(其可以是易失性动态随机存取存储器)中存在用于512个条目的空间,因此继而将来自非易失性存储装置1580的每一列A、B、C和D的128个条目读取到存储器1584中。一旦完成了四个读取中的每一个,可导出128个行,每个行包括来自四个列A、B、C和D中的每一个的条目。在各种实施中,每一列中的条目的大小可不同。因此,存储器1584中的存储空间可在列之间不均等地分割,其中存储较大条目的列接收较多的空间。这允许存储每个列的近似相同数量的条目。可替代地,存储器1584可在列之间均等地分配存储装置,从而导致存储较大条目的列一次将较少的条目存储在存储器1584中。随着行的导出,因此将需要早于条目较小的列将来自这些列的新数据加载到存储器1584中。索引存储区管理索引存储区可被配置成支持各种管理功能,诸如:快照拍摄、恢复、调整大小和迁移。这些特征可通过适当协调索引存储区写入和利用底层系统技术诸如Linux逻辑卷管理器(LVM)来实施。对索引存储区进行快照拍摄可用于备份,以便复制索引存储区或协助恢复。快照拍摄可通过以下方式实现:开始缓冲写入、将索引存储区闪存到磁盘、使用文件系统或卷管理器中的底层快照拍摄功能、以及然后施加写入。另外,对于基于诸如LevelDB的体系结构的系统,代替缓冲写入,系统可将数据压缩,将下层标记为快照的一部分,防止这些下层进一步压缩,复制包括下层的文件,并且随后重新使能压缩。恢复通过以下方式完成:根据底层系统恢复备份数据、开始索引存储服务、以及更新元数据服务指向恢复数据。所存储的元组ID集合在拍摄快照时被记录在元数据服务中,并且在恢复快照时被恢复。在从快照恢复之后,可通过将所有元组ID集合与存储在恢复的索引存储区中的元组ID集合进行比较来确定丢失的数据。使索引存储区缩减可通过将存储区中的所有数据压缩、减小文件系统的大小、然后减小逻辑卷大小来实现。如果存在用于移除磁盘(或虚拟磁盘)的足够自由空间,那么那个磁盘上的数据可迁移到卷组中的其他自由空间,磁盘可从卷组移除,并且随后从系统移除。使索引存储区增长如果必要的话可通过添加磁盘或虚拟磁盘来执行。如果添加了磁盘,那么磁盘可包括在卷组中,从而增加了逻辑卷大小,并且随后可增加文件系统的大小。在索引存储区的一些实施中,可以不使用文件系统,在此情况下索引存储区可实施调整大小操作而不是依赖于文件系统。在一些实施中,索引存储区可不使用LVM并且其本身可直接管理磁盘。在云环境中,或在服务器维护的过程中,可能期望将索引存储区从一个机器迁移到另一个机器。最简单的情况是离线进行这种迁移。这可通过以下方式完成:阻止读取和写入、关闭索引存储服务、卸载文件系统、禁用逻辑卷、将磁盘(或虚拟磁盘)移动到新机器、重新使能逻辑卷、安装文件系统、重新开始索引存储服务、以及更新元数据服务以便其知道给定索引存储区所处的位置。为了迁移在线的索引存储区,系统可缓冲写入并且在建立新索引存储区时执行从旧索引存储区的读取。随后将数据从旧索引存储区复制到新索引存储区,并且将新索引存储区标记为活动的。随后使读取针对新索引存储区,并且最终施加缓冲的写入。为了优化这种迁移,可从快照恢复新索引存储区。在这种情形下,缓冲了写入,并且可计算索引存储区的当前状态与快照之间的德尔塔。可施加德尔塔以便将快照带入最新的新系统。随后将新索引存储区标记为活动的,并且将缓冲的写入施加到新索引存储区。可在缓冲写入之前计算并施加多个德尔塔以使缓冲时间最小化。索引存储区扩展沿袭当将数据从一个数据存储区移动到另一个数据存储区时,可能期望能够在其移动通过系统时跟踪每个数据的沿袭。举例来说,考虑含有JSON记录的文件的集合,其中每个记录由换行符分开。可将来自这些文件的数据加载到索引存储区,并且将其从索引存储区加载到数据仓库。为了维持记录的沿袭,可例如通过记录每个记录的源文件名和行号来跟踪每个记录。可将沿袭信息作为额外列(或列集合)存储在索引存储区中。这些额外列还可加载到数据仓库中。这将允许终端用户能够找到记录的原始来源。用户可能想要这样做以便试图了解是否存在错误,或找到可能已删除或选择为不加载的其他数据。系统可使用那条信息来确定是否存在任何丢失的数据。(例如,通过文件和行分类并且找到是否存在任何丢失的文件或行)。类似地,并且可能具有类似的益处,当数据从索引存储区被加载到数据仓库中时,可在数据仓库中创建额外的列以记录索引存储区的元组ID。这可允许系统从某些错误中恢复,并且允许索引存储区与仓库之间的数据比较。时态/双时态支持时间是许多系统中的基本变量。理解时间字段的含义的系统改善了一些分析或甚至使其变得可能。保持对象的多种版本并且使用时间来区分这些版本的数据库通常被称为时态数据库。存在适用于对象的多个时间概念。两个常见的时间概念是事务时间(TT)和有效时间(VT)。事务时间是系统提交事务的时间。有效时间是一条数据有效的时间点或时间范围。例如,一个人所居住的特定地址与这个人居住在此处的特定时间段(VT)相关联。地址记录在系统中的时间是TT。在许多环境中,能够历史地观察数据是有益的。用于查询历史数据的一种机制是限定查询的ASOF特定时间点。人们可能希望系统能够基于在(ASOF)2014年1月31日可用的所有信息来回答问题。这些查询可检查具有小于或等于ASOF时间的最大TT的对象。在其他环境中,用户可能想要了解关于对象的事实如何随时间推移而改变的。这可能是一个人的记录在数据库中的家庭地址的许多版本,每个版本具有不同的有效时间。数据库用户可能想要执行对一个人的地址ASAT特定时间的查询。这个查询可检查其VT包含ASAT时间的对象。主要支持仅一个时间概念(通常为事务时间)的数据库被认为是单时态的。支持两个时间概念诸如事务时间和有效时间的数据库被认为是双时态的。双时态数据库支持对象的各版本的二维空间,并且支持通过询问查询ASOF特定TT和ASAT特定VT两者来使版本缩小。空间索引方法,诸如R-Trees、kd-trees和Z-ordering可用于沿多个维度建立索引,以使得在N维空间中彼此接近的对象在索引中彼此接近。为了暂时支持在索引存储区中,可针对时间维度创建另一个索引。这个索引可以是将事务时间映射到元组id的时态时间索引(TTI)。另一个索引可以是将有效时间映射到元组id的有效时间索引(VTI)。双时态系统可包括空间索引,以便将双时态索引(BTI)中的有效时间和时态时间映射到元组id。更新在各种实施中,如上所述的索引存储区可有效地处理批量插入或批量附加。这对于在具有硬盘驱动器的系统上进行查询和提取非常有效。有效地处理更新和删除(更新在以某种方式修改现有元组时发生)可能需要对索引存储区做出一些修改。这些更新可作为由某种事务存储区诸如MongoDB和其oplog做出的有序变化列表而到达。处理更新的一种方法是将更新应用到对象的就地值。因为在索引存储器中单行更新可能是昂贵的,所以这些更新可在写入优化存储区(例如,行存储区)中缓冲。参见图14,其中示出写入优化存储区1552。查询首先在写入优化存储区中查寻值并且随后查找索引存储区。当写入优化存储区中存在足够的数据时,可将数据组织成数据包以便在索引存储区中执行批量更新。用于处理更新的另一种方法是从输入中获取记录/对象并且基于某个键和记录在事务寄存器中的事务时间将它们转换成不同版本的记录/对象。随后可将所转换的记录/对象作为新记录附加到索引存储区。如果目的地存储区是暂时的,那么ASOF查询可用于在过去进行查询。数据变换当存在中间存储区时,可在从中间存储区导出数据时执行变换。这允许针对不同目的地进行不同变换并且可支持在应用任何变换之前创建源数据的单个定义明确的表示。当不使用中间存储区时,可在将每个列转换为关系时施加变换。类型变换一种常见的变换是将值从一种类型转换成另一种类型。举例来说,由于JSON不限定日期类型,所以常见的是将日期存储为字符串(例如根据ISO8601)或数字值(例如,自从UNIX时期的短时间内)。如果目的地支持日期类型(大部分关系数据库是这样),那么可添加改写指令以便将值转换为日期。类似指令可用于将适当字符串改写成数字。这些改写指令可使用数据的先前知识手动地指定或可使用在模式推断期间收集的统计信息自动推断出。数据清理可在导出期间执行多个其他数据清理操作。举例来说,如果已知属性是在某个域中(例如,字符串表示状态代码或数字表示邮政编码),那么值可省略或转换为默认值。拆分和联接数据如上所述,系统可将来自数组和映射的数据拆分成单独的表格,但在一些情况下用户可能想要对关系模式的附加控制。例如,他们可能具有多个源,他们想要将这些源组合到同一个目的地中,或者反之亦然。为了组合表格,用户可指定联接键并且联接可在导出之前在索引存储区中完成。为了拆分数据,识别一组列用于放置到单独的表格中。可使用全局唯一的记录id作为联接键并且单独地导出表格。这些列可以是手动地或使用诸如以上所述的那些的统计方法指定的,以便识别相关的属性集。被称为分解的操作基于单个属性的值将数据分区成表格。在单个属性的值确定记录的类型的情况下,这对于事件型数据源来说是特别有用的。可收集指定哪些列与每个id相关联的统计信息,并且可针对每个记录类型导出单独的表格。摄取目标数据仓库针对ETL过程的一个可能的输出目的地(或目标)是数据仓库。可通过根据动态模式的改变以行格式(例如CSV)创建一组输出文件连同一系列对应的ALTERTABLE/COLUMN命令以适应数据仓库来加载数据仓库。设计用于分析学的一些数据仓库,包括来自Vertica、Greenplum、Aster/Teradata和AmazonRedshift的产品使用单独存储不同列的面向列存储装置。在这些系统中,添加新的列不需要修改现有数据,并且可为更有效的。将文件加载到这种数据仓库可使用由所述数据仓库支持的命令来执行。以下描述供给可接受多个并行加载的目的地。非关系对象存储区用户可选择加载对象存储区而不是关系存储区。将数据加载到对象存储区中的一种方法是根据期望的输出格式使用累积JSON模式将对象串行化。协调可将ETL过程的各个组成部分排序并在分布式计算环境中执行,在云中或在私人数据中心内。排序可取决于数据源的性质、目的地、是否使用索引存储区以及所期望的并行化程度。可将流水线的每个阶段的状态存储在元数据服务中以支持恢复、统计和沿袭。示例ETL过程可分成以下组成部分:检测新数据(D);从源(S)中提取数据;推断源的模式(I);任选地加载索引存储区(L);产生累积模式(G);产生修改表格语句(A);任选地以中间格式导出数据(E);以及将数据复制到目的地(C)。使用以下伪代码来描述检测(D)过程的示例:使用索引存储区的摄取过程可包含提取数据(S)、推断模式(I)和加载索引存储区(L),它们一起被称为SIL。此处示出用于示例SIL过程的伪代码,其中索引存储区被称为“ISS”。此处示出用于示例产生模式过程(G)的伪代码:此处示出从索引存储区的示例导出过程(E)的伪代码:此处示出用于包括修改表格元素(A)和复制元素(C)、统称为AC的示例过程的伪代码:当不使用索引存储区,并且数据从数据源流到目标时,整个过程可被称为SIEGCA,其包含提取数据(S)、推断模式(I)、导出数据(E)、复制(C)和改变目标的表格(A)。此处示出用于示例SIEGCA过程的伪代码:在图16A-图16B中,示出根据本公开的原理的用于使ETL过程的组成部分并行化的关联图。图16A描绘中间索引存储区的使用。示出检测过程(D)分解成6个子过程1600-1......1600-6。用箭头示出关联性,其中D21600-2取决于D11600-1等。换句话说,D2不可能在D1已完成之前完成。当关联性严格时,如此处为了易于说明将描述的,D2甚至不能够在D1已完成之前开始。这可能如此是因为在D1已结束之前D2不知道从何处开始检测新数据,D1结束为D2留下起始点。仅举例来说,检测子过程D1可被配置用于获取第一10,000个新对象。子过程D2从子过程D1停止之处开始,并且识别下一10,000个新对象。图16A-图16B所示的关联性在某些情况下可中断。举例来说,如果D1和D2正在查看单独的数据源或数据源的不同部分,那么D2可开始而无需等待D1完成。提取过程(S)包括子过程1604-1......1604-6。每个提取子过程1604取决于相应的检测步骤1600。这种关联性源自以下事实:从源提取的文件/对象/记录是在检测子过程中识别的。在1608-1......1608-6处示出的每个推断子过程(I)取决于相应的提取子过程(S),因为模式推断是对在S中提取的记录执行的。针对推断出(I)的每个记录,那个记录被加载(L)到中间存储装置,因此加载子过程1612-1……1612-6中的每一个取决于相应的推断子过程。在1616-1……1616-3处所示的产生模式子过程(G)采取前一个模式并且添加来自一个或多个I子过程的新推断出的模式以产生新的累积模式。可使用试探法来确定被供给到单个产生模式子过程中的推断子过程的量。如图16A中所见,数量可变化。提取子过程1620-1……1620-3从相应的产生子过程接收所产生的模式并且从对应于产生子过程的加载子过程中提取数据。提取子过程1620可建立用于加载到目标诸如数据仓库中的一组中间文件。可优化每个子过程,包括提取子过程,以便利用内部并行化。基于产生子过程,修改表格子过程1624-1……1624-3产生使目标顺应由模式子过程1616确定的模式中的任何新对象的命令。举例来说,A2通过G2将累积模式与G1之后已存在的累积模式进行比较来确定是否已添加了任何附加对象。用于目标的命令可采取数据定义语言(DDL)语句的形式。虽然标记为修改表格子过程,但实际语言或语句可不使用特定语句“修改表格”。一旦修改表格子过程1624已将累积模式反映到目标,就在复制子过程1628-1……1628-3中将数据复制到目标中。在图16B中,示出流式方法,其中不存在中间存储区诸如列或索引存储区。替代地,数据直接被摄取到目标中,并且省略1612加载子过程。因此,提取子过程1620直接取决于模式推断子过程1608。还请注意,在这个实施中,修改表格子过程1624取决于复制子过程1628,这与图16A的关联性相反。弹性调度工作当使用索引存储区时,摄取任务(SIL)和导出任务(E)可以是计算密集型的。所述任务可在内部并行化。另外,假如满足它们的关联性,那么它们还可通过工作调度系统(例如PBS、LSF、YARN、MESOS等)异步进行发布。许多这些工作调度系统还可将步骤之间的关联性编码。通过了解关联图(诸如图16A所示),调度模块可在图中发布旧工作,以确保所有节点都是繁忙的,并且同时,并没有太多未完成的工作。错误恢复为了错误恢复的目的,一些或所有子过程记录关于系统的状态以及子过程意图在系统上执行的变异的元数据。如果步骤失败,那么恢复代码可使用这个元数据来完成中断的操作或退出不完整的操作以便其可再次尝试。例如,加载子过程记录正在加载的元组ID集合。如果加载子过程失败,那么可向索引存储区发布命令以指示具有元组ID的所有记录匹配待清除的集合。随后可再次尝试加载。优化导出一些关系存储区具有用于直接加载数据而不需要中间文件的机制。例如Postgres支持COPYFROMSTDIN命令,其中数据可直接供给至数据库。导出过程可适于这个接口来将数据直接写入到输出系统,从而将导出(E)步骤和复制(C)步骤合并。一些系统,诸如Amazon的Redshift,具有用于通过远程过程调用直接将数据从仓库拉到索引存储区的机制。在这种情况下,用户创建清单文件并且列出待发布用于进行复制的一组安全壳(ssh)命令。每个ssh命令指定主机和在那个主机上运行的命令。通过指定用于从索引存储区提取元组ID集合的命令,目的地数据库可将必需的记录/对象拉出索引存储器以便导出。监视资源监视监视系统跟踪系统使用的硬件和软件资源,所述硬件和软件资源可包括收集器、摄取流水线、元数据存储区、(任选的)索引存储区和数据仓库使用的计算和存储资源。监视系统跟踪以下量度:包括但不限于CPU、存储器和磁盘利用率,以及对网络请求的响应能力。如果服务部署在云中(公用或私有)或部署在具有以编程方式分配的资源的另一个系统上,那么可以使用监视系统来根据需要自动放大或缩小系统。举例来说,如果监视服务检测到索引存储区的存储空间(其可使用诸如AmazonEBS的服务来采取虚拟硬盘的形式)较低,那么监视服务可触发自动提供附加存储装置的请求而无需用户干涉。类似地,如果由摄取流水线常规地使用的工作机器具有较低的CPU利用率,那么监视服务可关闭机器。资源监视功能性可依赖于监视诸如Nagios的框架。摄取监视除了基本资源监视,可具体地对摄取流水线执行附加监视。关于摄取过程的每个阶段(模式推断、加载索引存储区、计算模式等)的元数据在摄取期间可存储在中心元数据存储区中并且可用于询问关于系统的量度。在最基本的层面上,这个机制可用于识别已停止或未正确起作用的进程。监视系统还可以跟踪哪些阶段自动重新开始以及每个阶段持续多长时间。这可有助于识别服务问题。此外,来自监视系统的历史数据可指示用户数据中的异常情况。举例来说,如果加载固定量的源数据所花费的时间显著地改变,那么可标记那个数据以便用户研究数据的什么特性可能已改变。查询监视监视系统可监视针对索引存储区或数据仓库所进行的查询的运行时间。通过观察类似查询的运行时间如何改变,可识别系统的潜在问题以及源数据的特性的改变。这个信息可告知数据仓库中的索引的使用或在索引存储区中规划的查询。举例来说,极少查询的列可不需要具有专用的索引,而在查询时经常以特定方式分类的列可得益于具有根据频率查询所分类的新索引。结论前述描述在本质上仅为说明性的,并且决不意图限制本公开、其应用或用途。本公开的广泛教示可按多种形式来实施。因此,尽管本公开包括特定示例,但本公开的真实范围不应如此受限,因为在研究图式、说明书和所附权利要求书后,其他修改将变得明显。如本文中所使用,短语A、B和C中的至少一个应当理解为意指逻辑(A或B或C),其中使用非排他性逻辑“或”。应当理解,一种方法内的一个或多个步骤可在不更改本公开的原理的情况下按不同次序(或同时)来执行。在本申请中,包括以下定义在内,术语模块可用术语电路替换。术语模块可指代以下各项、作为以下各项的一部分或包括以下各项:专用集成电路(ASIC);数字、模拟或混合模拟/数字离散电路;数字、模拟或混合模拟/数字集成电路;组合逻辑电路;现场可编程门阵列(FPGA);执行代码的处理器(共享、专用或群组);存储由处理器执行的代码的存储器(共享、专用或群组);提供所描述的功能性的其他合适的硬件组件;或以上各项的一些或全部的组合,诸如呈芯片上系统的形式。如上文所使用的术语代码可包括软件、固件和/或微代码,并且可指代程序、例程、函数、类别和/或对象。术语共享处理器包含执行来自多个模块的一些或所有代码的单个处理器。术语群组处理器包含与附加处理器组合执行来自一个或多个模块的一些或所有代码的处理器。术语共享存储器包含存储来自多个模块的一些或所有代码的单个存储器。术语群组存储器包含与附加存储器组合存储来自一个或多个模块的一些或所有代码的存储器。术语存储器可为术语计算机可读介质的子集。术语计算机可读介质不包含传播穿过介质的暂时性电信号和电磁信号,并且因此可被视为有形且非暂时性的。非暂时性有形计算机可读介质的非限制性示例包括非易失性存储器、易失性存储器、磁性存储装置和光学存储装置。本申请中所描述的设备和方法可部分地或全部地由一个或多个处理器执行的一个或多个计算机程序实施。计算机程序包括存储在至少一个非暂时性有形计算机可读介质上的处理器可执行指令。计算机程序还可包括和/或依赖于所存储的数据。当前第1页1 2 3 当前第1页1 2 3 
当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1