用于在单聚集过程中载入多数据集市的方法和装置的制作方法

文档序号:6500597阅读:300来源:国知局

专利名称::用于在单聚集过程中载入多数据集市的方法和装置的制作方法发明的背景本专利申请涉及载入数据集市的方法。数据集市是一个数据库或数据库的集合,设计用来帮助经理们对他们的商务活动做出战略性的决定。而一个数据仓库联合了整个企业的数据库,数据集市通常比较小并集中在一个特定的项目或部门。经常是,数据集市是一个较大的数据仓库的子集。RamonBarquin和HerbEdelstein编辑的《规划和设计数据仓库》(PrenticeHallPTR.ISBN0-13-255746-0)介绍了数据集市的定义和用法。RalphKimball编辑的《数据仓库工具包》(JohnWiley&amp;Sons.Inc。ISBN0-471-13337-0)提供了对数据仓库的背景和概念的良好的介绍。建立一个成功的数据集市的第一步骤之一是正确地识别在一个商业结构中的不同的维(dimension)和事实集(factset)。这通常被称为“维建模”。每个维表示一个独特的实体集合,其参与事实集,而独立于其它维的实体。事实集通常包括事务数据(transactionaldata),其中每个事务(或记录)由实体的集合对每个维一个个地识别。图1表示了一个超级市场的星型模式,其中星形模式是维建模过程的结果。每个维是一个表,其中每个记录包括一个唯一地表示每个实体的主键(或复合主键)和限定或描述相关实体(或主键)的属性(attribute)列表。在事实表中的每个事实记录应包括一个外码用于连接到每个维和表示事项处理数据的函数(measures)列表。因为维的大小通常比事实表小得多,维表通常不进一步的规范化(normalized)。因此,通过规范化节约的空间并不显著。并且,OLAP(联机分析处理)查询工具在查询运行期间连接规范化了的维并不节省时间。理论上,在上述的星形模式的结构中,OLAP工具可以直接查询包含事项处理数据的数据仓库。但是,为了达到高级查询的快速响应时间,例如,获得一种特定品牌的产品在每个州的月销售量的查询,必须要求数据仓库数据的预聚集。为了聚集的目的,每个维定义有数据层。根据条件每层定义了一组维条目(entry)。例如,在图1的商店维中,对不同的州定义有一个层,因此对每个具有至少一个商店的州层将包含一个聚集维记录。换句话说,一个特定的州的聚集维表示在这个州的所有商店的聚集。同样,我们可以在商店维中定义另一个城市层以便允许建立聚集维记录,其中每个条目表示一个特定的城市中所有商店的聚集。称为输入(或具体)层的层是最低的层并包括与输入维层相同的记录号。为聚集的目的由用户指定的层称为聚集层。每个聚集层根据层的条件包括不同的记录数。例如,州层可能包含比城市层少的记录。每个(输入和聚集的)层是由一个层代码唯一地表示。考虑到效率,层代码通常用一整数表示。在输出事实数据中需要的聚集由来自每个维一个的层的组合来定义。用于定义聚集的层的组合还称为层的交叉产品,以上述的星形模式中的查询某州某品牌的产品月销量为例,相关的层需要被定义从而根据三个特定的层的交叉产品,事项处理数据的聚集需要被要求。用户可以定义一个它们需要聚集的交叉产品的列表。输入层(或具体)的交叉产品表示输入或具体(detail)事实数据。对于每个要被具体的输入事实函数可能有一个或多个聚集表达式。一些常用的聚集表达式包括max(最大),min(最小),average(平均),sum(求和),count(记数),weightedaverage(加权平均)以及填入所聚集的数据的常量值。在每个维中通常还提供有一个“全值”层,其具有包含所有维条目的单体。当相关的维没有包括在交叉产品中时,此层用在交叉产品中,从而对每个维的包含一个层可以定义交叉产品的单一格式。在交叉产品中增加一个“全条目”层对聚集的结果没有影响,因此作为在交叉产品中的一个哑条目。例如,如果图1的星形模式被使用,需要月交叉产品的城市。产品的“全条目”层将被结合到交叉产品中。实际上,所有产品的数据被月聚集记录聚集到城市中。在聚集处理之后,产生一个数据集市。每个数据集市包含一套维和事实表。在数据集市中的每个维对应于在源星形模式中的一个维。在数据集市中的事实表包含特定交叉产品的列表的聚集数据。由当前受托者(assignee)提供的先前的产品是一项咨询服务,其识别在具体维记录和聚集维记录,事实数据聚集和聚集纬度和事实数据的分配之间的包含关系。前述的产品具有一个输出分配的基本机理。它可以将不同的具体和聚集维记录的层分配到不同的输出维文件/表中,把不同的聚集层交叉产品分配到不同的输出事实文件/表中。但是,它不真正地支持提供多数据集市的概念。只有一个目标(输出)星型模式配置被允许。它不支持不同星形结构配置的数据集市的概念。因此,产生的不同的输出维或事实表被限定在相同的输出目标星形结构配置。同样,前述的产品不允许在不同的目标事实表中不同聚集的产生。所有的事实表必须具有相同类型的聚集。但是,一组用户所关心的聚集可能另一组用户不关心。但是,允许不同的聚集可以节约在处理不必需的数据所浪费的资源以及限定可被客户访问的数据的范围。此外,维表不连接到任何特定的事实表。虽然产品可以产生多维和事实表,但数据集市的概念没有被执行以确保正确的维表被连接到正确的事实表。此外,用户可以确定一个维表以包含没有涉及它对应的事实表的交叉产品的层。在数据库系统中可能会非常错误地倾向于检查在维和事实表之间的标号完整性。现有的许多技术不具备足够的灵活性和效率以在单聚集产生过程中产生多数据集市。下面是为什么需要这样的灵活性和能力的原因。1)通常不希望产生具有被用户组需要的聚集的单数据集市,因为它可能包含其它用户组不需要的数据。此外,产生的一套聚集可能会太大而不能被复制或被在不同的物理位置的不同用户组所共享。2)小的特定的数据集市包含较小的数据量以及对目标用户组看来较不复杂的数据。查询指定的数据集市也更有效,因为较小或有限范围的聚集数据集。3)数据集市经常需要具有不同的目标星形结构配置和聚集,因为不同的用户组对不同系列的维属性或事实聚集感兴趣。此外,不同的用户组经常以不同的方式看数据。4)数据分配对节约存储资源是至关重要的。通常需要具有使不同的事实表共享相同的维表的能力。例如,两个数据集市,一个是用于实际销售而一个是用于预计销售。两个数据集市可以共享相同的维表;但是,每个数据集市会需要使它自己的事实表包含它自己的事实数据。5)运行聚集产生多次以产生特定的数据集市太昂贵了。做聚集多次的总耗费被禁止太高,因为它涉及读输入事实文件和分析在不同的聚集记录多次中的输入事实的容积。6)数据集市包含被OLAP工具使用的出版的数据以便有效的高水平查询。在数据集市中聚集的数据主要用于对有效的商务管理的决策支持。但是,不同的用户组可能要求与相同的一套事务数据不同的一套聚集数据。例如,西区市场组可能仅关心西区的数据,它可能从一套国家销售数据中有效地建立对不同的地理子集不同的数据集市。在另一方面,用户可能还需要与所有区域有关的数据如全国范围的销售图的总结。在此情况下,数据集市还可以包含一些重叠的聚集数据。系统包括3个主操作步骤维处理,聚集处理和数据集市分配。由于本发明主要涉及多数据集市建立,两个较早的聚集处理的步骤被假定为在执行所述的技术之前已经完成。实现维和聚集处理的技术是众所周知和现有的。在本发明的一个方面,对给定用户特定数据集市信息的多数据集市的总体提供了一个技术事实聚集列表,对每个维一个维数据列表。本发明的详细描述本发明的特定实施例将在后面做介绍。对每个要求输入此过程中的部件后面跟随着一个介绍作为本发明的实施例。用户必须为数据集市建立确定维和数据集市信息。这分别被称为维定义和数据集市定义。因此,用户必须确定维定义列表(每个维一个列表)和数据集市列表(每个要产生的数据集市一个列表)。在每个维定义中,用户必须确定下面的信息。这不包括维和聚集处理所需要的信息。1.维名称一个唯一的识别维的名称2.层条件和层代码聚集的层的列表用于聚集。每个层被一个层代码唯一地确定。层条件确定在每个层中的维记录的组3.维输出过滤标记(可选择的)维输出过滤标记控制在每个数据集市中要被输出的维记录。对每个维确定一个过滤选项。此标记不是所述的数据集市建立技术所必须的。换句话说,此技术可以在没有使用此标记的情况下执行;但是,它被包括在所述的执行过程的部分中,因为发现它在一些情况下很有用。以下是4个输出过滤选项a)无输出。对所有的数据集市的维表中不输出维记录。这在如果用户在输入维表中没有新的记录情况下有用。例如在超级市场图中,如果在产品维中没有新的产品,用户就对所产生的新的聚集不确定新的层,然后不需要产生维记录,因为它们应该已经存在在先前的聚集产生的数据库中。b)所有记录。在一个特定的数据集市的输出交叉产品中具有层代码的任何维记录将被输出到数据集市的维表。例如,在超级市场图中,如果州月销售品牌的聚集要被输出到数据集市,此输出选项被选择用于产品维,然后所有的品牌记录将被输出到数据集市的产品维表。这将包括没有在当前事实表中出现的品牌。c)在数据集市中有效。这是从“所有记录”选项的记录的子集。记录必须也在数据集市中有效以便被输出到它的维表中。如在前述的选项中给定的例子,品牌也必须在当前聚集处理(输入事实表)中有效以便维记录被输出到维表中。d)在任何数据集市中持续有效。这是从“所有记录”选项的记录的子集。记录必须也在当前或任何前述的数据集市的聚集中有效以便被输出到它的维表中。如在前述的“所有记录”选项中给定的例子,品牌也必须在当前或任何以前的聚集中有效以便维记录被输出到维表中,对于从未加入到数据集市的输出事实数据中的品牌,它们不会被输出到维表中。对每个数据集市定义,用户必须确定如下信息。4.数据集市名称一个唯一的名称识别数据集市5.层交叉产品列表这是所有的层组合的列表,其应该具有在当前数据集市中计算出的聚集。如果当前数据集市需要输出输入事实数据,层组合的列表会包含输入层交叉产品的条目。在一最简单的情况下(一个维),这就简化了层列表以建立聚集。每个层交叉产品相应于每个维具有一个层代码条目。在交叉产品中的层代码的顺序应该对应于在维定义列表中确定的维的顺序(这不是必须的,但是如果这样可以使事情简化)。6.维表定义列表维表定义列表对每个维包含一个维表定义登录项。每个维表定义包含列(column)信息,如列位置,数据类型,确省值和其他的数据库相关信息。此外,对每一列,用户还需要识别是否它是一个码列或属性列。对于属性列,每一列对应于一个输入属性列。用户可以确定一个维表定义与在另一个数据集市中的相同维的另一个表定义相同,而不是对一个维确定一个新的表定义。在此情况下,两个数据集市将共享相同的目标维表。两个数据集市的维的输出记录将被并入相同的目标维表。确实,一个或多个数据集市可以将它们的维数据输出到相同的目标表中。7.事实表定义(包括产生的函数的列表)每个数据集市定义将包括一个事实表定义。一个事实表定义包括列信息如列位置,数据类型,缺省值,和其他数据库相关的信息,此外,用户还需要确定哪些是主键列,哪些是函数列。应该有一个主键列对应于每个维。主键列的数据类型必须与在维表中定义的主键列的数据类型一致。每个函数列应该对应于函数定义。每个函数定义根据聚集类型确定输入事实表的一个聚集类型和一些函数列。在当前的优选实施例中,支持如下聚集类型maximum(最大),minimum(最小),sum(求和),average(平均),weightedaverage(加权平均)(其包括要平均的列和一“权”列),count(计数)和fill(填充)(将一给定的值放置到聚集中)。其他类型的聚集可以方便地结合到实施例中。用户可以从另一个数据集市确定一个事实表定义,而不是对当前数据集市确定一个新的事实表定义。在此情况下,两个数据集市将共享相同的目标事实表。两个数据集市的维的输出记录将被并入相同的目标事实表。确实,一个或多个数据集市可以将它们的事实数据输出到相同的目标表中。事实聚集的列表是聚集产生过程的输出。它包含在输出和聚集层两者中的事实数据。事实聚集的列表用做本发明的数据集市分配算法的输入之一。每个事实聚集记录包含加入到每个维中的主键、交叉产品层代码组合和聚集测度的列表。记录有如下的逻辑表达;对每个维应该有一个外码。外码最好用整数表示(如它们在当前的最佳实施例中)因为它们比较较快,但是还可以选择其他数据类型。在记录中的主键的理想情况是与在数据集市结构中的维定义列表的顺序相同。但是这不是必须的。它们可以被重新映射到所希望的顺序,如后面要介绍的。层代码组合表示当前聚集记录对应的交叉产品层组合。每个层代码表示每个维的聚集或具体层。如果层代码具有与在数据集市结构中确定的维定义列表相同的顺序,它可以被简化。但是,这不是必须的。根据层代码组合,做出是否聚集记录需要被写入特定功能的数据集市中的决定。层代码组合还可以包含所有维的具体层代码。在此情况下,记录是一具体层事实记录,函数可以包含与相应的聚集类型的输入事实记录相同的值。一些数据集市乐意要求要写出的具体层聚集。函数是为记录所产生的聚集。函数的列表必须是所有数据集市要求的所有函数的超集。函数可以以任何顺序排列。如在下面部分所要介绍的,函数的顺序可以重新映射到数据集市所需要的顺序。由于事实聚集记录的字段没有以任何预定的顺序排列,用户还需要限定事实聚集记录的定义。定义应该包含事实记录字段的列表。每个字段定义包含一个枚举(numeration)以表示是否字段是一个主键、层代码或函数。如果字段是一个主键或层代码,它的字段定义应该包含一个维定义的参数。如果字段是一个函数,它的字段定义将包含一个函数定义。事实记录定义使得分配过程知道每个字段向什么并相应地重新映射每个字段。对每个维有一个维记录列表。它包含输入层和聚集层两者的维记录。每个维记录包含一个主键,一个层代码,一个属性列表和一个可选的持续有效转换。维记录列表还用做本发明的数据集市分配算法的输入。下表表示一个维记录的逻辑图。主键字段包含当前维记录的码。它是在当前优选实施例中的一个整数值用于快速比较。层代码是一个唯一的层标识,以表示当前记录的(具体或聚集)层。层代码是在当前优选实施例中的一个整数值用于快速比较。属性1到属性a表示记录的属性值。对于具体记录,它们包含与输入维记录相同的值。对于聚集记录,一些属性可以包含空值因为它们是记录被聚集采用的属性。例如,一个品牌维记录可以不将产品名称属性填入,因为每个品牌记录是许多单个的产品名称的聚集。可选持续有效转换是布尔值,它说明现有的纪录在任何一种数据集市中或在任何以前的聚集生成过程中是否为持续有效。这种转换同用来过滤维输出的选择维输出过滤标志一起使用。如前所述,多个数据集市载入技术并不需要输出过滤功能,但发现该功能在被用户作为载入过程的一部分时会有用。如果不使用持续有效转换,维纪录列表就无须继续存在了。如果要使用持续有效转换,那么维纪录和转换需要同时存在以保证“数据集市的持续有效”输出过滤选择能够正常运行。在本发明优选的实施例中,为了维持维纪录的持续可视,为每一个维提供一个主数据库。在数据集载入期间,该标志一直作为一种登记功能。本文后续将作进一步阐述。因为维纪录的字段没有在任何事先设定的序列中列出,用户还需创建一个维纪录定义。该定义包含一个维纪录字段定义的列表。字段定义含有一个计数以指出该字段是否为一个主键,属性,或是持续有效的转换。如果字段是一个属性值,它的字段定义就会含有一个输入维列的参考。而主键字段或是持续有效转换就不需其他附加信息。维字段定义能够使分配过程明确每一个字段的含义并能够相应地重新映射每一个字段。图2表明了上述不同表与列定义之间的包含关系。本发明的数据集市载入技术同以往的载入技术的很大不同在于在每个数据集市中,它将维表与事实表紧密地联系起来。在一个单一的聚集生成过程中,它允许载入多个数据集市。每一个数据集市都能代表一个包含不同维属性和不同聚集的星形模式。而且,该过程还允许数据分割,这样数据集市可以共享同一个维或同一个事实表。因此,从不止一个数据集市中产生的维或事实表会包含在这些数据集市中合并了的数据。本发明特定实施例的系统包括如下几个部分数据集市结构,事实记录器和维记录器(1计数器/维)。下文将对这三种主要系统构件的每一种设计和主要操作过程作逐一阐述。基于以上用户指定信息,图3描述了信息可以被内部分析和构造。这就是数据集市的结构。该结构主要是为其它系统构件获取用户指定的数据集市属性提供接入方法。上述的数据集市结构是通过分析用户指定信息而构建的。在数据集市结构中的交叉产品表包括一个交叉产品层代码序列和数据集市位向量对。在每个交叉产品中的层代码的排序与维定义表中指定的相同。数据集市位向量的位与数据集市定义列表指定的排序相同。交叉产品表包含一个所有数据集市都需要的唯一的交叉产品层代码集。它是通过合并由每个数据集市指定的交叉产品层代码而得到的。该表由层代码组合分类以提高查找速度。为了便于快速比较,目前较理想的实施方法是将层代码采用整数值。与每个层代码相关联的是位向量,由它指出交叉产品所属的数据集市。通过解析每个数据集市中的层交叉产品序列,在表中添加新的层交叉产品目录,和将当前新建和已建的目录下的数据集市的向量位置1,交叉产品表中的数值就被创建出来了。通过进一步分析数据集市定义,就可列出函数定义列表和量度位向量列表。函数定义列表包括所有数据集市所需的唯一的函数定义集。而向量的获得是通过找出每一个数据集市中的每一个事实表所需的唯一函数来实现。每一函数定义由它的输入函数列聚集和它的聚集类型(如SUM,MAX,MIN等)所唯一标识。每个数据集市的函数位向量列表包含一个条目。每个函数位向量表示与它相应的数据集市所需的函数。通过对每个数据集市的每个事实表执行循环语句,即可对这两个表进行初始化。所需的主要步骤由下列假代码表示出。//martDefList,measureDefList,和measureBitVectorList是数据集市定义列表,函//数定义列表和函数位向量列表,它们分别都保存在数据集市结构中。<prelisting-type="program-listing"><![CDATA[InitializeMeasuresInfo(){  //初始化列表  measureDefList.clear();//首先找出函数定义的唯一集for(i=0;i<martDefList.size();i++){vColumns=  martDefList[i].factTableDef.GetColumns();//在目标表中对每一列作循环for(j=0;j<vColumns.size();j++){  if(vColumns[j].IsMeasure()){  //检查函数定义是否已经在现有的函数定义列表中foundIndex=findMeasureDef(measureDefList,  vColumns[j].GetMeasureDef());  //是否为新函数  if(foundIndex==-1)  measureDefList.AppendEntry  (vColumns[j].GetMeasureDef());  }}}//在列表中添加函数位向量每个数据集市添加一个位向量for(i=0;i<martDefList.size();I++){vColumns=  martDefList[i].factTableDef.GetColumns();//初始化函数位向量bitVector=0;//在目标表中对每一列执行循环for(j=0;j<vColumns.size();j++){  if(vColumns[j].IsMeasure()){  //从列表中找出函数定义应该找出函数定义  foundIndex=findMeasureDef(measureDefList.  vColumns[j].GetMeasurDef());  measureBit=1<<foundIndex;  bitVector=bitVector/measurBit;  }}//在列表中添加所需函数的位向量measurebitVectorList.AppendEntry(bitVector);}}]]></pre>一旦创建了数据集市结构,其它系统组成部件就能够查询用户指定的参数。下列列表列出了所有数据分布技术所需的接入方法。1)获取全部函数定义vMeasuresDef=GetMeasureDefinitions()const在函数定义列表中获取常量参考值。向量包含所有数据集市所需的全部的唯一函数。每个函数定义包括聚集类型和其输入函数列的信息。numMeasures=GetNumMeasures()const在数据集市结构中获取所有的函数数量。它与函数定义列表的大小相同。2)获取函数定义索引index=getMeasureIndex(constmeasureDefinition&amp;def)const在数据集市结构的函数定义列表中找出指定的函数定义。若在列表中找出该函数,则方法返回“0”索引值。如果没找到指定的函数定义,则方法返回“-1”。3)获取所有维定义vDimensionsDef=GetDimensionsDefinitions()const在维定义列表中获取一个常量参考值。向量包含所有的维定义。每个维定义都含有维输出过滤标志,层代码和条件。numDimensions=GetNumDimensions()const在数据集市结构中获取全部维数。它与维定义列表的大小相同。3)获取维定义索引index=GetDimensionIndex(constdimensionDef&amp;def)const在数据集市结构的维定义列表中找出指定的维定义。若在列表中找出指定维,则方法返回“0”索引值。若没发现指定维定义,方法返回“-1”。4)获取全部数据集市定义vDataMartsDef=GetDataMartDefinitions()const在数据集市定义列表中获取常量参考值。向量包含所有数据集市的定义。每个数据集市定义都包括维和1.1.4节中所述的事实表定义。5)为交叉产品获取有效数据集市vMartBits=GetActiveMarts(constcrossProductLevelCode&amp;xprod)const设定一个交叉产品层组合。它确定了在事实输出中需要用哪一个数据集市来产生指定的交叉产品。具体地,它通过搜索交叉产品表来找出指定的交叉产品。返回的位向量索引同数据集市定义列表的索引值相同。位集为“1”表示相应的数据集市要求产生/输出指定的交叉产品。6)为数据集市获取有效的函数vMeasBits=GetActiveMeasures(constdataMartDefinition&amp;rMart)constvMeasBits=GetActiveMeasures(intiMart)const设定一个数据集市定义或一个数据集市索引。通过它即可为指定的数据集市获得函数位向量。返回的位向量索引与函数定义列表的数值相同。位集为“1”表示数据集市要求相应的函数。7)为层代码获取有效的数据集市vMartBits=GetActiveMarts(constdimensionDefinition&amp;rDim,constlevelCode&amp;code)constvMartBits=getActiveMarts(intiDim,constlevelcode&amp;code)const获取需要在指定维输出的指定层的维纪录数据集市。这种功能实际上是在交叉产品表中执行循环,从而在每个交叉产品组合中找出与该表相匹配的指定维的指定层代码。然后从每个已建目录中传输(bitwise)数据集市位向量的Ors值。返回的位向量索引与数据集市定义列表的索引值相同。位集为“1”表示相应的数据集市要求产生/输出输入的层交叉产品。8)设定一维和一个数据集市来获取有效层代码vLevelCodes=GetActiveLevels(constdemensionDefinitin&amp;rDim,constdataMartDefintion&amp;rMart)constvLevelCodes=GetActiveLevels(intiDim,intiMar)const通过设定一维和一个数据集市定义,或是与之对应的索引的方法,就可以从指定维中获得一个唯一的层代码列表,因为层是位于指定数据集市的交叉产品列表中。对于一个特定的数据集市,维纪录是否输出到目标表,须依照层是否参与其事实表的任何交叉产品组合,和维输出过滤标志的数值而定。“事实记录器”是用于为所有数据集市产生事实表的功能组件。它将事实聚集和其记录定义作为输入,为其它用户指定参数进行数据集市结构查询,并且对每个数据集市输出一个事实表。值得注意的是,如果指定多个数据集市将其纪录合并成一张表,那么一张事实表就会响应多个数据集市。如前所述,每个聚集纪录包含一个主键列表,层代码和函数。然而,主键,层代码和函数不必同数据集市结构中的维定义列表和函数定义列表的顺序相同。它们的顺序被指定在事实聚集记录定义中。因此,需要对“事实记录器”建立一个映射方案,使它能够重新定位数据集市结构中基于维及函数顺序的聚集纪录中的列。在内部,需要对事实记录器建立一个主键向量,一个层代码位置向量和一个函数位置向量。主键和层代码位置向量的大小与维数相同。函数位置向量的大小与数据集市结构中的函数定义列表的大小相同。实际上,这些向量中包含事实聚集纪录中主键、层代码和函数的列位置。它们用来重新标定这些列,以使事实记录器在数据集市结构中指定的同一维或函数序列中处理聚集纪录。以下假代码描述了建立各种不同的位置向量的主要过程。其中所描述程序的输入是数据集市结构。//程序执行后,便创建了KeyPosVect,xProdPosVect,和measurePosVect向量,这//些向量用来重新映射事实聚集列。向量的每一项都将含有事实聚集纪录中的相//应列的位置。<prelisting-type="program-listing"><![CDATA[ConstructRemappingVectors(){  //初始化位置向量的大小keyPosVect.resize  (dataMartStructure.GetNumDimensions());  xProdPosVect.resize  (dataMartStructure.GetNumDimensions());  measurePosVect.resize  (dataMartStructure.GetNumMeasures());  //对事实聚集纪录的字段定义执行循环  for(i=0;1<factAggRecordDef.size();i++){  if(factAggrRecordDef(i).IsKey()){  dimDef=  factAggrRecordDef[i].GetDimensionDef();  //从维定义列表中查找维定义索引  foundIndex=  dataMartStructure.GetDimensionIndex(dimDef);  keyPosVect[foundIndex]=i;  }  else  if(factAggrRecordDef[i].IsLevelCode()){  dimDef=  factAggrRecordDef[i].GetDimensionDef();  //从维定义列表中查找维定义索引  foundIndex=  dataMartStructure.GetDimensionIndex(dimDef);  xProdPosVect[foundIndex]=i;}  else{//函数列  measureDef=  factAggrRecordDef[i].GetMeasureDef();  /从数据集市结构的函数定义列表查找函数定义索引  foundIndex=  dataMartStructure.GetMeasureIndex  (measureDef);  //忽略在任何数据集市中无效的函数  if(foundIndexi=-1)  measurePosVect[foundIndex]=i;  }  }}]]></pre>“事实记录器”还须在指定的每个数据集市定义中分析事实表定义。它需要保留一个所有数据集市都要求的唯一的目标表定义列表。与每个目标表定义相关联的是一个数据集市位向量,一个布尔向量和一个位置向量,该向量将主键和函数的位置重新定位到目标表的最佳位置。每个唯一事实目标表所需的信息列在以下假代码结构中factTableInfo{factTableDef;//数据集市结构中的事实目标表定义dataMartBitVector;//数据集市列表合并到目标表中isKeyVector;//表示主键和函数的布尔向量positionVector;//表示映射位置的整数向量};下列假代码指出了怎样建立上述信息<prelisting-type="program-listing"><![CDATA[//事实表信息列表将与唯一目标表信息同时被初始化InitializeFactTablesInfo(){//清空储存在事实纪录器中的目标表信息factTableInfoList.clear()//从数据集市结构中获得数据集市信息martDefList=  dataMartStructure.GetDataMartDefinitions();//循环每个数据集市for{i=0;i<martDefList.size()i++){  //检查当前的数据集市事实表是否已经出现在factTableInfoList中  foundIndex=findTableDefinition  (martDefList[i].factTableDef.  factTableInfoList)  martBit=1<<i  if(foundIndex>=0){//是否找到  //标示出在同一张目标表中的当前数据集市也有效  factTableInfoList[foundIndex].dataMartBitVector=  factTableInfoList[fondIndex].dataMartBitVector  martBit  }  else{//建立一个新的目标表目录  factTableInfo.factTableDef=martDefList[i].factTableDef  factTableInfo.dataMartBitVector=martBit;  //在表中获取列定义列表  vColumns=  martDefList[i].factTableDef.GetColumnDefs();  //将主键向量的大小设为列的个数  factTableInfo.isKeyVector.resize  (vColumns.size());  factTableInfo.positionVector.resize  (vColumns.size());  //在目标表中对每一列执行循环  for(j=0j<vColumns.size0;j++){  if(vColumns[j].IsKey()){  factTableInfo.isKeyVector[j]=true;  //找出数据集市结构中的dimDef索引  dimIndex=  dataMartStructure.GetDimensionIndex  (vColumns[j].dimensionDef);  factTableInfo.positionVector[j]=  dimIndex;  }else{//是否列为一个函数  factTableInfo.isKeyVector[j]=false;  //在数据集市结构中找出vColumns[j].measureDef的索  //引  measureIndex=  dataMartStructure.GetMeasureIndex  (vColumns[j].measureDef);  factTableInfo.positionVector[j]=  measureIndex;  }  }  factTableInfoList.AppendEntry(factTableInfo);  }//否则  }//循环}]]></pre>该假代码在基于数据集市结构信息的事实记录器中写入了唯一的事实目标表信息列。此程序在每个数据集市中执行循环并检查它的目标表定义。首先,它要查找目标表定义是否已在当前目标表列表中。若有,那就意味着另一个数据集市已将其结果输出到该事实目标表中了。因此,找出的目标表信息目录的数据集市位向量就会被设为当前数据集市的位值。如果数据集市将其结果输入到一个新事实目标表中,列表中就会增加一个新目标表信息目录。而其数据集市位向量的空值就会被设为当前数据集市的位值。同时,为了重新定位目标列,还要写入布尔及位置向量。布尔向量与位置向量的大小应与目标表的列数相一致。布尔向量的一个条目表示输出列是否为主键或是一个函数。如果输入列是主键,那么此时位置向量的对应值应该显示为主键读入的维索引;如果输入列是函数,那么此时位置向量的对应值就应该显示为数据集市结构中函数定义列表的函数索引。当“事实记录器”被设定成一个由主键和函数组成的列表,以相同的顺序,分别做为维和函数定义列表时。这些索引将会被用来重新定位列图4用实例描述了全映射机理的工作过程。在“事实记录器”内部数据结构初始化完成之后,“事实记录器”能够开始读事实聚集的列表并将这些聚集分布到不同的事实目标表中。“事实记录器”只需读聚集列表一次。对于每个记录,都将被重新映射,并重新分配每一个映射记录到每个参与的目标分配表中。如下的伪代码函数描述了多目标表分布,给出一个聚集记录的过程。<prelisting-type="program-listing"><![CDATA[WriteAggregateRecord(aggrRecord){  //填写预分配(或数据成员)主键、xprod,以及在聚集纪录  中重新映射  //的函数列表  for(i=0;i<dataMartStructure.GetNumDimensions();  i++)  keys[i]=aggrRecord[keyPosVect[i]]  xProd[i]=aggrRecord[xprodPosVect[i]]  }  for(i=0;i<dataMartStructure.GetNumDimensions();  i++)  measures[i]=aggrRecord[measurePosVect[i]];  //为当前交叉产品获取有效数据集市  activeMarts=dataMartStructure.GetActiveMarts(xProd);//在每个唯一目标表中执行循环  for(i=0;i<factTableInfoList.size();i++){  //是否当前目标表中的记录有效  if(activeMarts&amp;  factTableInfoList[i].dataMartBitVector){  //在每一列中执行循环  for(j=0j<factTableInfoList[i].isKeyVector.size();j++){  position=facttableInfoList[i].positionVector[j];//在预分配输出纪录中重新定位主键和函数列  if(factTableInfoList[I].isKeyVector[j]==true)  outputRecord[j]=keys[position];  else  outputRecord[j]=measures[position];  }  //输出记录至目标表  writeRecordToTable(outpuRecord);  }  }}]]></pre>用一个外部循环来读每一个聚集记录,并且通过调用这个函数去写记录到每一个目标分配表中。那么上面函数的运行多次次数应与聚集记录的输入列表的记录数相等。函数首先要重新定位输入聚集记录到主键、交叉产品和函数这三个列表中去。映射的主键和交叉产品的列表顺序应与数据聚集结构维定义列表顺序相一致。然后,函数为当前聚集记录的交叉产品确定有效数据集市。对于每个至少参与一个有效数据集市的目标表来说,主键和函数列表都将被重新映射到目标表中必要的列位置上。请注意,如果记录是作为数据集市结构预期的预指令,那么从输入聚集记录来重新定位列的第一步就是没有必要的。如本文件结尾所解释,在聚集生成中,可以使用数据集市结构来实现。既然,它不是对数据集市提供技术的要求,更多的通用方法已被使用的,那么这一假设不会被认为是一个先决条件。“维记录器”是一个功能组成部分,负责对所有的数据集市,生成一个维的维目标表。它将形成一个多维记录列表,包含输入、查询用户指定参数的数据集市结构和为每个数据集市输出一个维表。注意,当多个数据集市被指定合并其记录到相同的维表时,这个维表将对应多于一个的数据集市。“维记录器”必须设置一些内部信息之后才能开始数据分配。首先,必须要根据输入维记录的定义找到主键字,层代码和持续有效转换位置。对维记录中的每个字段的定义可由循环来完成,如下面所示的伪代码所描述。它能将找到的主键,层代码,有效转换位置保存到“维记录器”的内部变量中去。<prelisting-type="program-listing"><![CDATA[//定义KeyPos输入维记录的主键位置//定义codePos输入维记录的层代码位置//定义SwitchPos输入的有效开关位置//定义记录{  dimKeyPos=-1;  dimCodePos=-1;  dimSwitchPos=-1;  for(inti=0;i<dimRecordDef.size();i++){if(dimRecorddef[i].IsKey())  dimKeyPos=i;  elseif(dimRecordDef[i].IsLevelCode())  dimCodePos=i;  elseif(dimRecordDef[i].IsActiveswitch())  dimSwitchPos=i;  }}]]></pre>在进行多个维表分配之前,对于每个维表记录要求一个预处理步骤,去获取对每个维记录的有效数据集市位向量。该位向量被用来辅助涉及输入数据集市输出过滤选项。如果输出过滤没有执行,那么这个预处理步骤也会被取消。预处理步骤的输出是对每个维的数据集市位向量列表,其中,每一个数据集市相应于一个维记录。位向量预处理步骤能够通过读一次事实聚集记录,可同时载入对所有维的数据集市位向量列表。最初,所有维的数据集市位向量列表被设定为0,之后对每个事实聚集记录,建立对每维的主键和层代码。使用“为交叉产品获取有效集市的方法,建立与每维层交叉产品相关的数据集市位向量”。对于每一个关键字,利用匹配关键字,从相关的维记录列表建立维记录。,最后,已建的维记录的数据集市位向量将与刚从数据集市获得的数据集市位向量进行“或”运算。建立的维记录因此被认为在指定的数据集市位向量的数据集市内有效,以及在任何已与显现在其它交叉产品相连的数据集市内有效。因而读事实聚集列表一次,所有维的数据集市位向量将被载入。在聚集生成过程中,预处理步骤的作用是较佳的,然而,数据集市位向量列表的初始化是优选的数据集市载入技术,除去预处理步骤,去提供一种较普通的方法。维记录器也必须对指定在每一个数据集市的当前维询问数据集市结构和分析维表定义信息。内部地,维记录器需要保持一个由所有数据集市要求的唯一的维目标定义列表。与每一个维表定义相关的是一个有效数据集市位变量,一有效层码列表,一个用于重定位主键及属性到要求位置的位置向量。对每个维目标表需要的信息如下面结构所示。<prelisting-type="program-listing"><![CDATA[dimTableInfo{  dimTabledef;//定义目标表  //定义数据集市结构  dataMartBitVector;//数据集市列表合并为这个目标表  levelcodeVector//包含表的有效层代码列表  positionVector;//表示映射位置的整数向量};下面伪代码表明如何构造上述的信息//一个维表信息列表同唯一目标表信息被初始化InitializeDimTablesInfo(){  //清除贮存在维记录器中的目标表列表信息dimTableInforList.clear();  martDefList=  dataMartStructure.GetdataMartdefinitions();  //curdimdef是当前的维定义  curDimIndex=  dataMartStructure.getDimensionIndex(curdimDef);  for(i=0;i<martDefList.size();i++){  //检查当前数据集市的维表是否已出现在dimTableInfoList中foundIndex=findTabledefinition  (martDefList[I].dimTabledef[curdimIndex].dimTableInfoList);  martBit=1<<i;  if(foundIndex>=0){//若找到  //添加当前数据集市至数据集市位向量中  dimTableInforList[foundIndex].dataMartBitVector=  dimTableInforList[foundIndex].dataMartBitVector/  martBit;  //将当前有效层代码列表合并至已建好的目录中  vCodes=getActiveLevels(curDimIndex,i);  mergeDistinctLevelCodes  (dimTableInfoList[foundIndex].levelCodeVector,  vcodes);  }  else{  //建立一个新的目标表目录  dimTableInfo.dimTableDef=  martDefList[I].dimTableDef[curDimIndex];  dimTableInfo.dataMartBitVector=martBit;  dimTableInfo.levelCodeVector=  GetActiveLevels(curDimIndex,i);  //从表的列中获取列表  vColumns=  martdefList[i].dimTableDef.GetcolumnDefs();  for(j=0;j<Vcolumns.size();j++){  if(vColumns[j].IsKey()){  //输入维记录的主键位置  dimTableInfo.positonVector[j]=dimKeyPos;  }else{//列属性  //输入维记录的主键位置  dimTableInfo.positionVector[j]=  dimRecordDef.FindInputColumn  (vColumns[j].GetInputColumn());  }  }//循环  }  }//循环}]]></pre>该伪码基于数据集市结构来的信息,在记录器内载入了独立的维目标表信息。它对每一个数据集市循环并检查当前维的目标表定义,首先,寻找目标表定义是否已在目标表列表,如果找到,意味着另一数据集市已输出它的结果到相同的维目标表。因而,当前数据集市的位将置入到已建的信息条目的数据集市位变量。而且,用于当前数据集市的有效层码的列表将并入到已建条目的层码变量。如果,数据集市下输出到一个新维目标表,一个新的表信息条目将被加入到表中。当前数据列表的位将置入到初始端数据集市位向量。层码向量条目将被载入到当前数据集市的有效层列表。最后,位置变量将包含索引或来自维记录的列位置。向量被用来对从维记录被输出到目标表的列的重定位。当维记录器内部数据结构初始化后,它可以开始读维记录列表并分配记录到不同的目标表。维记录器仅需读记录列表一次,对每个记录,都会被重新映射并将已映射的记录分配到每一个参与的目标表。下列伪代码函数描述了多个目标表分布的过程,设定一个维记录及它的相应有效数据集市位变量。<prelisting-type="program-listing"><![CDATA[  WriteDimensionRecord(dimRecord,activeMarBitVector)For(i=0;i<dimTableInfoList.size();i++){  ActiveInTabel=  ActiveMartBitVector&amp;  dimTableInfoList[i].dataMartBitVector;  LevelInTable=findLevelcode  (dimTableInfoList[i].activeLevelCodes.  dimRecord[dimCodePos]);  outputRecordFlag=false;  //更新持续有效开关  if(activeInTable)  dimrecord[dimSwitchPos]=true;  //依据输出过滤选项确定是否输出记录  if(filterOption==AllRecords){  if(levelInTable)  outputRecordflag=true;  }  else  if(filterOption==ActiveInDataMarts){  if(levelInTable&amp;&amp;activeInTable)  outputRecordflag=true;  }  else  if(filterOption==EverActiveInDataMarts){  if(levelInTable&amp;&amp;  dimRecord[dimswitchPos]==true)  outputRecordFlag=true;  }if(outputrecordFlag==true){  for(j=0;j<  dimTableInfoList[i].positionVector.size();j++){  position=dimTableInfoList[i].positionVector[j];  outputrecord[j]=dimRecord[position];  writeOutputRecord(outputRecord);  }  }//循环}]]></pre>有效数据位变量是预步骤的输出。应有一个外部环路去读每一个维记录并调用这个函数把记录写入到每一个参与的目标表。因而,这个函数调用的次数与输入维记录到表次数相同。函数循环经过维目标信息列表,它首先初始化两个标志,activeInTable和levellnTable。activeInTable表明当前维记录在事实内是否有效,levellnTable表明是否当前维记录在现有的目标表的层码列内。然后它升级现存的持续有效转换。如activeInTable标志为真时,转换为真。根据过滤选项,逻辑运算确定是否当前的维记录应被输出到目标表。如果记录被输出,主键和属性将重新映射到目标表的列位置。应当注意到,“EverActive”标志与每一个输入维记录相关时,可以使用一个“EverActiveinDataMarts位向量来替换。这可以允许维记录被输出到目标数据集市,如果这些数据曾接受了相应于数据集市的事实数据。然而,这要求保持现存的数据与输出数据集市相关,最好在输入维表中。在聚集中,这造成了维持输入事实数据与输出数据集市定义同步的问题,因为这个原因,它没有使用在所描述的优选实例中。使用在较佳实施例的“EverActive”标志,不包含任何依赖于输出数据集市构造的数据。这就造成以下问题使输入事实数据保持与输出数据集市同步,由于这个原因不能在此介绍的优选实施例中执行。在优选实施例中执行的“持续有效”标识不包含任何取决于输出数据集市的数据。系统部件的操作和其间的数据流在以下介绍。图5描述了输入要求中给定的数据流的概述以及在前述部分中介绍的系统部件。如图所示,数据集市结构必须在分配开始之前被构成。一旦数据集市结构启动,用于维记录的预处理步骤可以发生。预处理步骤为所有的维记录定理和事实聚集记录定义建立了主键和层代码的字段位置。此后,开始读取事实聚集记录的列表。对每个事实聚集记录,就会更新所有事实聚集记录的相关维度记录(每个维度一个)的数据集市的位向量。预处理步骤在早先已介绍过,参见“维编写器”。当预处理完成后,“事实编写器”和“维编写器”开始并行操作。“事实编写器”以事实聚集记录列表作为输入值,查询数据集市结构,为每个数据集市产生一个事实表。每个“维编写器”以维记录的列表和它的相关的从预处理步骤产生的数据集市位向量的列表作为输入值,查询数据集市结构并为每个数据集市产生一个维度表。因此,编写器不具备任何的相互关联,它们可以独立地执行它们的任务。但是,如果数据集市在数据库上被装载到表中,其中引用完整性(referentialintegrity)被执行,在任何特别情况下,所有的事实数据的主键值必须在维度数据中有相应的值。如果事实编写器写入了一个登录项,之后所有的它相关的主键值被维编写器所编写,就会有中断引用完整性。如果编写器被在这样的环境下使用,当处理完成时在开始处理和重新使能之前,引用完整性必须被设为禁用。另外,只有当维编写器完成处理过程时,事实编写器可以被设置以开始。下面是本发明的数据集市载入技术的主要有益之处和优点的总结。1)允许在单聚集产生过程中多数据集市的建立。2)由于数据集市可以覆盖聚集要求或者聚集的相同水平,有更高的资源效率以产生多数据集市。它消除了额外的读取输入事实文件和多次产生相同的聚集桶。3)允许数据集市具有不同的星形结构和不同的聚集。每个数据集市的结构被修整或目的在于满足不同用户组的需要。4)在维表中的记录紧密地联系到在事实表中的聚集记录。只有如果记录层加入到相关事实表的输出交叉产品列表中,记录在维度表中。产生的数据集市往往错误要少得多。5)允许数据分配为大数据集。逻辑分配的数据集市可以合并和共享维表以避免在具有不同的事实表时维数据的不必要的复制。由于具有灵活的数据集市分配的结构,数据可以被分配或合并到不同的维或事实表中。6)灵活的维输出过滤结构允许用户选择维记录的正确的集合以被输出到维表。在本文件中提供的技术目的在于覆盖更普遍的情况。为了优化技术,可以应用其它的合理的假设。本部分介绍了一些可能的优化的各种情况。如前所述,维输出过滤标识不是本发明的数据集市载入技术所必须的。提供此技术是增强维记录分配的能力。提供了逻辑值即4个输出过滤选项无维输出,所有维记录,在数据集市中激活,和在数据集市中一直激活。附加的输出过滤选项可以根据其它的激活的数据集市或层代码标准的组合而增加。“在数据集市中持续有效”输出过滤能力要求维记录一直可见地保持下去,因为每个维记录需要根据时间保持“持续有效”标识。如果“在数据集市中持续有效”过滤能力不需要被支持,维记录也不需要保持不变。在所述的技术中,除了要有需要的所有的函数的子集外,对在事实聚集记录中的函数不做假设。而且,对事实聚集记录和维记录的字段位置也不做假定。在优选实施例中,做了一些合理的假定,因为数据集市结构在产生聚集之前被建立。在聚集产生之前,用户应该有所有的维和数据集市定义是相当普通的。在聚集产生之前给定数据集市结构,已知一组需要的函数。在数据集市结构中的维和函数的顺序也已知。在此情况下,层代码和在每个事实聚集记录中列出的函数也可以有一些预定的顺序,例如,在记录中的首先的N字段可以是如在数据集市结构中规定的维的相同顺序的主键字段,在接下来的N字段可以是如在数据集市结构中规定的维的相同顺序的层代码字段,最后的M字段可以是与在数据集市结构中规定的相同顺序的函数。在此情况下,事实聚集记录的初始的重定位步骤可以被消除。对维记录,为了优化的目的,主码、层代码和持续有效可以被假定位于前3个字段。如果数据集市结构在聚集产生之前被建成,载入数据集市位向量的预处理步骤也可以被消除。在聚集产生的同时可以实现此任务。然后,仅为了载入数据集市位向量的目的就不需要读取事实聚集列表。在优选实施例中,当一个输入事实记录使聚集进入所有的它的加入的聚集桶,与输入事实记录有关的所有维记录的数据集市位向量和它的聚集桶将要被更新。更新位向量的逻辑与在“维编写器”中所述的相同。但是,在此情况下,它取消了多一次读取事实聚集记录的需要。再就是,在每个维中数据集市位向量被用于输出过滤的目的。如果没有过滤被支持或所支持的过滤选项不需要数据集市位向量,载入数据集市的步骤可以被取消。虽然本发明的优选实施例被显示和介绍,显而易见对于本领域的技术人员而言在不偏离本发明的精神的情况下可以做一定的改变和修改,本发明的范围被所附加的权利要求所限定。权利要求1.一种从一个一级数据集市产生许多输出数据集市的方法,所述的一级数据集市包括输入事实数据和至少一个维表,所述的方法包括以下步骤a)产生聚集的事实数据包括许多记录,表示所述的事实数据在一层或多层而不是输入事实数据层的总和。b)分配所述的聚集事实数据到所述的许多输出数据集市,其中,某些聚集的事实数据记录被分配到多于一种所述的数据集市,和其中分配到至少一些输出数据集市中的事实数据集记录是不相同的。2.按照权利要求1所述的方法,其中,每一聚集的事实数据记录只产生一次,然后,输出到要求所述的聚集事实数据记录的输出数据集市中。3.按照权利要求1所述的方法,进一步包括以下步骤提供至少一种数据结构说明被每一输出数据集市要求的层或层交叉产品;建立聚集事实数据记录,其需从所述的输入事实数据中产生;生成每一个要求的聚集事实数据记录,及对每一个生成的聚集事实数据记录1)从所述的输出数据集市要求的至少一个数据结构,建立所述的聚集的事实数据记录;及2)向每一所述的要求所述的聚集事实数据的输出数据集市提供所述的聚集事实记录。4.按照权利要求3的方法,其中,所述的数据结构包括至少一个维的一层列表或层交叉产品,及其中,所述列表中的每一元素与一种或多种输出数据集市相关联,因而,允许每一聚集的事实数据记录与基于与记录相关的层或层交叉产品的适合的输出数据集市相关联。5.按照权利要求1所述方法,其中,聚合的事实数据是被不同的数据集市所分享。6.如权利要求1所述方法,进一步包括从一个输入维表,对每一输出数据集市产生维表的步骤,其中每一产生的目标维表仅包含与被相关的数据集市要求的层相关的维记录。7.如权利要求6的方法,其中,至少一种生成的维表被两种或多种输出数据集市所分享。8.权利要求6的方法,其中,对一特定的维产生目标维表的步骤是,生成与所述目标维表相关的层列表,及仅当与所述维记录相关的层是在与所述目标维表相关的层列表中时,输出维记录到一个目标维表。9.如权利要求8的方法,其中,生成一特定的目标维表的层列表是在与每一数据集市相关的合适维中,将层列表并入到相应的目标维表,其中,与特定数据集市相关的每一个层列表包括与数据集市相关的所有交叉产品的相应维中的一组层。10.按照权利要求9的方法,其中,在每一个数据集市生成的维表仅包含来自所述的输入维表的记录,其显现在输出到数据集市的聚集的输出事实数据中。11.如权利要求10的方法,其中,对每一个数据集市,在一特定的维中,产生维表的步骤是a)对于每一个与数据集市相关的维记录,提供存储方法及对没有与数据集市相关的每一个维记录进行初始化;b)对于每一事实数据条目,完成下列步骤,其中,每一事实数据条目包括对应于每维中的一特定维记录的一组维条目;1)在每一维,建立与维条目相关的层。2)根据所述层的交叉产品,建立与所述事实数据条目相关的数据集市,及对于每一维,如果数据集市还未与所述的维条目相联时,在所述的存储方法中,使每一所述的数据集市与相应于维条目的维记录相联。c)如果在所述的存储方法中,与输出维表相关的一数据集市与维记录是相联的,则输出每一维记录到每一输出维表。12.按照权利要求6所述的方法,其中,产生的维表被不同的输出数据集市所分享。全文摘要一种在单聚集处理的数据库中所包含的一组事项数据的单操作中,载入多数据集市的方法,其中聚集值仅被计算一次,要做出一个决定,即哪些除数据集市需要聚集值以及聚集值被输出到合适的数据集市。与输出聚集记录相关的维数据也被输出到合适的数据集市。文档编号G06Q10/00GK1384939SQ00808023公开日2002年12月11日申请日期2000年5月24日优先权日1999年5月24日发明者伊娃·曼-扬谢,迈克尔·迪安·洛尔,詹姆斯·丹尼尔·阿塔韦申请人:计算机合伙思维有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1