近年来,电子信息数据在企业的运营中越来越重要,企业需要对电子信息数据进行高效、及时、精确的分析。传统的数据仓库通常只支持历史数据的分析与查询,不能实时捕获数据源中的变化,因为它们采用ETL工具周期性地从数据源中抽取数据,对其处理后加载到数据仓库,而数据抽取的频率通常为一个月一次、一周一次或者一天一次[1]。在实时数据仓库中,实时数据导入与实时数据查询的冲突将严重影响联机在线分析(On-Line Analysis Processing,OLAP)的精度和效率。
当前解决这个问题的方法有很多,包括提高数据库的性能、增加外部实时数据缓存[8]、即时(just in time)合并外部数据缓存信息、反向即时数据合并、实时分区、主动分区等等。但是上述方法在查询结果的精度和效率上不能兼顾。
为解决查询竞争并提高查询结果精度,本文提出一种动态镜像技术。动态镜像技术是在实时数据仓库的外部创建一个动态存储区域,源系统中数据导入数据仓库时,先在动态存储区域创建一个分区并在其中创建一个节点,同时将数据存入节点。当这部分数据同时有更新需求和查询需求时,则利用复制机制新建一个与存储该数据的节点物理结构、逻辑结构都相同的节点。新数据存入新的节点,当新数据导入完成后,再次进行查询,保证了查询结果的精度,且避免了查询竞争。
改进的实时数据仓库架构与传统数据仓库不同的是,改进架构的ETL[2]过程被分割为定期ETL与实时ETL两个部分。定期ETL是将数据源中的数据定期以批处理方式直接导入数据仓库,而实时ETL则运用改变数据捕获(CDC)[3]技术将源系统中变化数据加载到动态存储区域。经过查询、更新和删除等操作,当满足系统的触发条件后,这些数据才会以批处理方式载入数据仓库。
数据仓库的存储区域被分为实时数据存储区和历史数据存储区,实时数据查询和存储在实时数据存储区实现。实时数据仓库的更新查询调度模块能够根据用户的需要决定查询和更新等操作序列;数据质量模块在展示数据查询结果时生成一份报告,以便用户知道这些数据内容和新鲜度;查询控制模块实现在动态存储区域进行实时数据查询操作。对于历史数据查询,动态存储区域与数据仓库需要无缝连接,以保证查询结果的精度。
为了克服实时OLAP(Real-Time OLAP,RTOLAP)查询中的多表连接和分组聚集的性能瓶颈,采用物化策略可以减少RTOLAP在动态存储区域中表连接操作访问基表和中间数据结构的次数。首先,RTOLAP将查询分解为作用在维表和事实表上的子查询,子查询将生成〈key,value〉二元组;然后,扫描事实表一趟,利用事实表的外键映射直接定位相应二元组,完成多表连接或聚集操作。为了提高RTOLAP多表连接或聚集性能,本文提出蝇量级物化下的表连接算法FWMJoin(Fly-Weight Materialization Join)。
本文采用的基于动态镜像的实时数据存取技术在不同的事务更新频率下,查询效率可靠,如果给予动态存储区域更大的内存空间则性能会更好。
本文采用基于TPC-H的实时数据仓库测试系统,从OLAP响应时间、查询精度方面对动态镜像技术、单镜像、无镜像方案进行比较与分析。实验结果表明,基于动态镜像的实时数据存取技术能有效解决查询竞争问题,提高数据存取效率和查询结果的精度。
动态镜像是一种实时数据仓库存储预处理技术,主要用于解决数据仓库的查询竞争问题[9]。面对实时数据仓库中的查询与插入的竞争问题,近年来开展了许多研究工作,包括提高数据库的性能、增加外部实时数据缓存、即时(just in time)合并外部数据缓存信息、反向即时数据合并、实时分区、主动分区等。
(1)单独实时数据缓存方法是使用一种与数据仓库分离的外部缓存。外部数据缓存持续更新,数据仓库使用ETL工具以批处理模式进行数据更新,所有的实时数据或准实时数据的查询直接定位到外部的数据缓存,从而避免了在数据仓库中的查询竞争问题[7],但如果数量巨大的复杂查询分析运行在外部实时数据缓存,则同样会发生在数据仓库中出现的查询竞争问题。
(2)简化和限制实时报表方法,需要实时数据的用户只能发出简单的查询要求,限制复杂查询语句。这种方法可以消除查询竞争,但是无法满足用户对复杂查询的要求。
(3)升级硬件,可以为高端的SMP数据库系统增加更多的节点或者为数据仓库配备更快的处理器和更大的内存。这种方法能在短期内解决问题,但是增加了成本并且可扩展性低。
(4)反向即时数据合并[4],就是把所需要的历史数据临时地反向加载到实时数据缓存中,查询在缓存中进行。这种方法可以有效解决查询竞争,但是查询结果的精度却不尽理想。
(5)实时分区[5]是将实时数据进行数据量均衡的分区,然后分别对各分区数据进行查询导入操作。这种方法有效缓解了查询竞争,但是关于分区的个数和数据量的均衡算法的研究一直未成熟,分区算法随着分区个数增加,其时间复杂度也线性增加,海量数据环境下给系统带来沉重的负担,难以满足实时性的要求[11]。还有主动分区[6]等技术,它们都难以满足用户的需要。
当连续实时地导入数据时,用户的查询操作受到严重影响,包括查询结果的精度和查询效率。因此,实时数据仓库面临实时数据导入和实时数据查询相冲突的问题,即当ETL在向实时存储区加载数据时,用户如果正在对实时存储区进行多次查询,这几次查询都将纳入同一个统计结果,那么就要考虑是否将新到来的数据纳入结果中。如果不做任何处理,OLAP查询结果的精度往往难以满足要求,需要设计一种新的结构来解决此问题。
本文设计一种基于动态镜像的实时数据仓库预存取技术,系统结构如图1所示。其包括3个部分:
(1)实时数据仓库改进,包括分类ETL结构和将数据仓库存储区域分为实时数据存储区和历史数据存储区。
(2)在数据仓库外部构建动态存储区域,动态存储区域由多个数据镜像与基于双重链接的镜像索引组成。
(3)动态镜像管理,包括镜像创建与回收、基于双重链接的镜像索引维护。
首先是ETL分类。对于实时数据,数据在时间有效性范围之外(即失效)将成为历史数据。因此,撒尿BBWBBWBBW毛对于实时数据的ETL处理同样是分为历史ETL和实时ETL。实时ETL通过CDC技术捕获OLTP系统中查询任务提交时间之后更新的数据并加载到动态存储区域,在动态存储区域对数据进行查询、更新、删除,当满足系统触发条件后再以批处理方式存入到数据仓库中的实时数据存储区;历史ETL将OLTP系统中查询任务提交时间之前存在的数据以批处理方式存入数据仓库的历史数据存储区域。
其次是数据仓库存储区域分为实时数据存储区和历史数据存储区。历史数据是指由历史ETL将OLTP系统中的数据处理并存入数据仓库的历史数据存储区的数据;实时数据是指先由实时ETL将OLTP系统中的数据处理并存入动态存储区域,然后根据触发条件由动态存储区域存入数据仓库的实时数据存储区的数据。
动态存储区域由多个数据镜像与基于双重链接的镜像索引组成。镜像是具有相同的逻辑结构和物理结构的数据存储区域,并根据数据查询任务的需求,在动态存储区中动态创建;系统可以将OLTP中的实时数据加载至镜像中。
当创建一个镜像时,系统在动态存储区中保存一个相应的镜像文件,用四元组表示:
其中,image_address表示镜像在动态存储区中的首地址,image_size表示镜像分配的存储空间大小,data_id表示镜像存储的数据源,timestamp表示数据的时间戳。
根据每个镜像文件中的data_id,将所有data_id相同的镜像构建成一个镜像链表Link_img,如图2所示。镜像链表Link_img由链表头节点img_head和链表节点img_node组成,链表头节点img_head由镜像数据源data_id与指向链表第一个节点的地址head_next组成。在一个镜像链表中,所有镜像的数据源来自同一数据源,数据源data_id相同。指向链表第一个节点的地址head_next存放第一个镜像首地址image_address。根据镜像文件内容,链表节点img_node由镜像大小image_size、镜像数据时间戳timestamp、操作标识符tag,及指向下一个链表节点的地址img_next组成。操作标识符tag用于记录当前镜像数据的操作类型,其初始值为0;若当前镜像内容节点的数据是从源数据库系统OLTP导入至动态存储区,则此镜像内容节点的操作标识符置为0;若当前镜像内容节点的数据需要从动态存储区批量加载至数据仓库的实时数据存储区,则操作标识符置为1;对于当前镜像而言,若在动态存储区中,不存在来自同一数据源的镜像,则img_next设为空;否则,img_next存放下一个来自同一数据源的镜像的首地址image_address。
同一个镜像链表中存储了来自同一数据源但是更新时间不同的数据镜像信息;随着系统运行,最近更新数据的时间戳一定大于较早更新数据的时间戳,所以,镜像链表中的节点按其数据时间戳倒序(从大至小)排序。
所有来自同一数据源的镜像构成一个镜像链表,称之为一个镜像桶bucket,如图3所示。其中镜像桶的首地址bucket_address为链表头节点地址。
在动态存储区中,若存储了n个数据源的数据,就有n个镜像桶。为了加快镜像数据的查找与定位,将对多个镜像桶采用链表结构,构成一个镜像桶链表Link_bucket。镜像桶链表Link_bucket是一个无链表头节点的链表,仅仅由镜像桶链表节点bucket_node构成。
每个镜像桶链表节点bucket_node由数据源data_id、镜像桶的首地址bucket_address与指向下一个镜像桶链表节点的地址bucket_next组成。其中,数据源data_id存放对应的镜像链表的数据源data_id;镜像桶的首地址bucket_address存放对应镜像链表头节点地址;向下一个镜像桶链表节点的地址bucket_next存放下一个镜像桶的地址bucket_address;若动态存储区中不存在任何数据,即不存在任何数据源的镜像桶,则不存在镜像桶链表;在动态存储区中,若只有一个镜像桶,则其bucket_next为空;否则,bucket_next存放下一个bucket_address。
通过镜像管理模块可以得知在动态存储区域中哪些镜像用于查询而哪些镜像用于ETL的更新数据,这样由多个镜像构成的动态存储区域就可以实现持续数据的实时装载。这种动态镜像的方法不但有效地解决了查询竞争问题,同时也提高了实时数据的查询精度。传统的数据仓库在更新的过程中进行“批”加载[8],本文通过建立由动态镜像组成的实时存储区使新鲜的数据不断载入,以达到数据的持续更新,从而大大提高了查询结果的精度。
动态镜像管理包括镜像创建与回收,及基于双重链接的镜像索引维护。首先动态存储区域空间有限,其次从源系统载入数据到动态存储区域中的镜像,其物理地址不一定是连续的,所以需要有效地分配、收回管理才能保证动态存储区域中数据的查询和导入有条不紊地进行。
镜像的创建过程就是将实时数据存入实时存储区域的过程。算法步骤如图4所示。
该算法的具体操作流程如下。
(1)当有新的数据需要从OLTP系统加载至动态存储区时,动态镜像管理模块在动态存储区中分配一块存储空间,创建一个镜像,用于存储新数据;同时,系统在动态存储区中保存一个相应的镜像文件。
(2)动态镜像管理模块采用顺序查找方式,遍历镜像桶链表中的每个镜像链表节点,检查新数据的数据源是否与镜像链表节点的数据源相同,即检查动态存储区中是否存在与新数据属于同一数据源的数据。若存在,则转入(3);否则转入(9)。
(3)根据镜像桶链表节点的桶镜像首地址,可以查找到来自同一数据源的镜像链表的头节点。
(4)为新创建的镜像,在对应的镜像链表中创建一个新的镜像链表节点,操作标识符tag设为0,指向下一个链表节点的地址设为空。
(5)根据新节点时间戳,将新镜像链表节点插入至相应的镜像链表。在镜像链表中,镜像节点按其数据更新时间戳倒序(从大至小)排序,所以,新镜像链表节点n的时间戳最大,将其插入在链表头节点之后。
(6)对于镜像M而言,若镜像的数据满足查询条件,或者接收到系统操作指令,需要将数据批量地从动态存储区导入数据仓库的实时数据存储区时,将镜像链表节点的操作标识符tag设为1,同时,相应的数据批量地写入数据仓库的实时数据存储区。
(7)对于镜像M而言,若系统接收到数据更新指令,此时,动态镜像管理负责检查同一数据源的镜像数据是否正在从动态存储区导入数据仓库的实时数据存储区。
若存在,正在导入数据的镜像内容节点无法进行更新操作,则动态镜像管理在动态存储区采用步骤(1),分配存储空间,创建镜像,更新所属同一数据源的镜像链表,并接收来自OLTP的更新数据。以此类推,若需要将不断更新的数据导入动态存储区,系统不断分配存储空间,创建后续镜像,更新镜像链表,转入(11)。若不存在,则转入步骤(8)。
(8)动态镜像管理模块在动态存储区中分配存储空间,创建镜像,用于存储新数据。同时,系统在动态存储区中保存相应的镜像文件。
(9)为新数据源的镜像创建一个新的镜像链表。链表头节点的数据源ID存放镜像文件四元组的数据源;指向链表第一个节点的地址存放新创建的镜像首地址。镜像节点的操作标识符tag设为0,镜像节点的指向下一个链表节点的地址设为空。
(10)根据新创建的镜像链表更新镜像桶链表。在原镜像桶链表的尾部增加一个新镜像桶链表节点。镜像桶链表节点的数据源存放新数据源ID,镜像桶链表节点的首地址存放新创建的镜像链表的首地址,镜像桶链表节点的指向下一个镜像桶链表节点的地址设为空。
(11)动态镜像创建完毕,基于双重链表的镜像索引也完成相应的更新。
(1)对于镜像M而言,当系统将镜像的数据批量地从动态存储区导入数据仓库的实时数据存储区完成后,实时数据仓库系统将发送反馈信息至动态镜像管理模块。
(2)动态镜像管理模块根据收到的反馈信息,释放导入镜像数据所占用的存储空间。
(3)动态镜像管理模块根据镜像的数据源ID和镜像桶链表节点的首地址,定位到同一数据源的镜像链表中对应的镜像链表节点,将其节点从镜像链表中删除。
(4)若删除镜像链表节点后,其所属镜像链表的节点个数为0,仅存在链表头节点时,则动态镜像管理块将此镜像链表所对应的镜像桶链表节点从镜像桶链表中删除,并释放其占用的存储空间。
本文采用时间戳匹配法处理实时数据仓库查询请求,请求过程如下:
(1)若实时数据仓库系统已运行,根据用户发出的查询请求,镜像管理模块首先获取请求的时间戳和data_id。
(2)然后根据data_id在动态存储区中查找相应的镜像,如果没有,则返回空值,并将查询请求发送至数据仓库处理;否则,在对应data_id的镜像链表中顺序查找,转(3)。
(3)在相应的data_id镜像链表中,按时间戳从大到小查找。若时间戳失效,则返回空值,并将查询请求发送至数据仓库处理;否则,读取与请求最匹配的镜像节点数据,并将结果返回至用户。
镜像链表中镜像按时间戳从大到小有序存储。若存在某一节点的时间戳小于或等于请求的时间戳,且其前一个节点的时间戳大于请求的时间戳,则说明此节点数据按时间戳匹配原则,最佳满足用户请求,所以,返回此节点的数据至用户。图5显示了在镜像链表中处理用户查询请求的实例。
从分析可知,查询竞争严重影响查询效率和查询结果的精度,动态镜像是一种实时数据仓库存储预处理技术,用于解决数据仓库的查询竞争问题[9]。当一条数据载入数据仓库后,首先判断数据是否为实时数据,如果是,则被实时ETL捕获,经过一系列清洗、过滤操作后载入动态存储区域。为了说明动态镜像技术是如何解决查询竞争问题的,本文假设所有新捕获的数据都是同源数据,即数据具有相同data_id,且动态存储区域已经存在该数据的同源镜像链表。当数据第一次加载至动态存储区时,为其建立相应的数据镜像,命名为M1,同时插入相应的镜像链表中。当镜像M1中的数据时间戳失效时,将其导入数据仓库中。后续同源的数据再加载至动态存储区时,系统也建立相应的数据镜像,命名M2、M3,并插入镜像链表中,以此类推。镜像M1数据由于实时性失效,被载入数据仓库后,为用户提供历史数据的查询分析,而存放于镜像M2、镜像M3中的实时数据加载至动态存储区后,为用户提供实时数据查询分析功能。通过时间戳比较匹配方法,来满足用户实时性要求,提高查询结果的精度。通过合理、高效的数据分配和管理,基于动态镜像的数据存取技术可以有效地解决查询竞争问题。
对于传统关系数据仓库而言,在数据更新阶段,实时数据以批处理模式加载至存储区时,由于查询竞争,会导致数据更新丢失,影响数据查询精度[10]。本文提出的动态存储区可以动态地为实时数据分配镜像存储空间,缓解查询竞争压力。时间复杂度作为衡量算法质量的重要指标,关系到算法的执行效率。下面对动态镜像创建、回收过程进行时间复杂度分析。
(1)动态镜像创建的时间复杂度是由数据导入的频率决定的。最坏情况为数据查询过程中不断有更新数据导入,则时间复杂度为O(n2);最好情况为数据查询操作恰好在数据导入完成后进行,则时间复杂度为O(n)。
(2)动态镜像回收过程是在操作完成后,回收数据所在的镜像桶空间,时间复杂度为O(n2)。
本文利用空间换取时间思想,以内存空间为代价,减少数据I/O开销,提高查询效率和查询结果的精度。
OLAP上的查询分析操作一般表现为在事实表和维表之间连接操作的基础上对结果集进行分组聚集等操作。因此,表连接和分组聚集操作是关系联机分析处理(Relational OLAP,ROLAP)性能的两个重要决定因素。为了提高实时OLAP进行基于多表连接查询的数据分析性能,期望查询执行算法能够采用一趟扫描机制完成表连接、过滤与聚集等操作。下面给出本文提出的蝇量级物化下的表连接算法FWMJoin(Fly-Weight Materialization Join)。本文提出的蝇量级物化连接算法FWMJoin是LWMJoin[13]算法的改进。LWMJoin是针对星型模型的数据仓库,基于轻量级物化而提出来的表连接算法,它分为3个阶段:首先,将维表上的谓词条件作用在相应维表上,产生三元组〈surrogate,key,value〉,抽取符合过滤条件的元组构建哈希表;然后,顺序扫描事实表,利用事实表外键映射函数定位相应维表的三元组;最后,根据过滤三元组确定是否访问事实表相应位置上的元组构建结果集。如果三元组中的key值存在为false,那么该元组应舍弃;否则,将key值与事实表度量属性拼接成一条元组,并将该元组以流水线方式输入到下一个操作。
FWMJoin对LWMJoin的改进如下:将invisible join中由元组关键字构建的哈希表替换为Chord环。通过结合DHT(Distributed Hash Table)技术,将维表中符合过滤条件的元组的关键字所在的内存地址的哈希值作为节点标识符(Node ID),并对元组的关键字进行散列运算,产生一个唯一的资源标识符(Object ID),且该资源将存储在节点标识符与之相等或相近的节点上。使用事实表外键作为关键字(key)进行查找。Chord与其他结构相比较,具有负载均衡、鲁棒性高、可扩展和命名灵活等特点。
作为一种优化实时数据仓库性能的手段,动态存储区域下的动态镜像实时数据仓库的存取预处理技术必须与实时数据仓库结合使用。本文实验部分将动态镜像技术与基于多级缓存(multi-cache)的实时数据仓库结合。
影响计算机系统性能的因素是多种多样的,加上其应用环境也特别复杂,基本不可能使用一个准确、固定的公式来表达,常用衡量的方式是指通用的基准程序。TPC-H是一种基准,用来衡量数据库系统在硬件、软件方面联机分析处理的性能以及对DSS支持的能力[12]。这一基准是由事务处理性能委员会(TPC)在1999年公布的。通过测量给定的数据库单位时间内能够处理事务的数量来测试数据库性能。
本文选用来自Sean Lahman[14]网站的结构化数据。Sean Lahman网站详细记载了从1871年到2014年美国职棒大联盟(Major League Baseball)各支球队和各个运动员的比赛数据。本文在Hive中建立16GB空间的实时数据仓库,约350万条记录。
(1)统一设置动态存储区域大小为128MB,无镜像方案没有动态存储区域,不设置。从图6中可以看出,使用动态镜像技术在事务更新频率为1.0s/次的情况下,这是测试基准最低开销,响应时间增长率都趋于0。当事务更新频率设置为最高值时,每次间隔0.1s需处理一个事务,OLAP响应时间也达到最大,动态镜像技术相比于单镜像提升约1倍,与不采用镜像技术相比,性能提升接近3倍。随着事务发生频率增大,本文提出的动态镜像技术响应时间变长,但即使在事务成倍增加的情况下,使用动态镜像技术的响应时间的增长还是可以控制在50%以内。这种效率是完全可以接受的,同时也在用户满意的范围。
(2)统一设置事务更新频率为0.5s/次。如图7所示,在条件相同的情况下,动态存储区域的空间越小,OLAP的响应时间则越长。当动态存储区域为32MB时,对于OLAP查询操作,单镜像与动态镜像方案响应时间相当,动态镜像方案略占优势。但是,当存储空间较大时,对于OLAP操作,动态镜像和单镜像方案的查询响应时间明显占优。动态镜像方案的查询响应时间比无镜像方案快1.8倍,比单镜像方案提升约16%。
(3)设置事务更新频率为0.5s/次,动态存储区域统一为128MB空间。从图8中可以看出动态镜像技术、单镜像技术及无镜像3种情况在不同的事务更新频率下的实时数据查询结果精度。当事务更新频率较低时,3种方案的查询精度较为接近;当事务更新频率设置为0.1s/次的最高频率时,动态镜像技术的查询结果精度达到85%,单镜像技术的精度为73%,而不采用镜像技术的精度为48%。本文提出的体系结构随着事务发生频率增大,平均精度达到89.3%。
实验结果表明,当实时数据被不断加载时,本文采用的基于动态镜像的实时数据存取技术在不同的事务更新频率下,查询效率可靠,如果给予动态存储区域更大的内存空间则性能会更好。
结束语本文提出的基于动态镜像的实时数据仓库预存取技术是一种空间换时间的技术。通过在实时数据仓库外部创建一个由多个镜像组成的实时存储区域,有效地解决了实时数据仓库的查询竞争问题,并且提升了实时数据查询结果的精度。另一方面,在海量数据的背景下,如何进一步提高实时数据查询的精度,以及保证实时数据新鲜度,将在后续的研究中展开。
标签:
上一篇: 自动化立体仓库在备件存储方面的应用
下一篇: 海外代购中保税仓库问题研究