行ID进行排序由于Accumulo表,每个表都可以被认为是被索引的行ID。行ID进行查找,可以快速执行,做一个二进制搜索,第一个冲过片,然后在平板电脑。客户应小心选择行ID,以支持其所需的应用程序。一个简单的规则是选择行ID为每个实体的唯一标识符来存储和分配所有其他属性进行跟踪,根据此行的ID列。例如,如果我们有一个逗号分隔的文件中的下列数据:
userid,age,address,account-balance
我们可能会选择此数据存储使用的的ROWID,其余列家庭中的数据的userid:
Mutation m = new Mutation(new Text(userid));
m.put(new Text("age"), age);
m.put(new Text("address"), address);
m.put(new Text("balance"), account_balance);
writer.add(m);
作家。(米);
通过指定的用户ID作为扫描仪的范围和获取特定的列,然后我们就可以检索任何一个特定的用户ID列:
Range r = new Range(userid, userid); // single row
Scanner s = conn.createScanner("userdata", auths);
s.setRange(r);
s.fetchColumnFamily(new Text("age"));
for(Entry<Key,Value> entry : s)
System.out.println(entry.getValue().toString());
7.2。ROWID设计
通常,它是必要的,以便有预期的访问模式最适合的方式,是命令行变换ROWID。一个很好的例子,这是互联网域名的组成部分,以相同的父域组行的顺序颠倒过来:
com.google.code
com.google.labs
com.google.mail
com.yahoo.mail
com.yahoo.research
有些数据可能会导致在创造非常大的行 - 行有许多列。在这种情况下,表设计可能要拆分这些行更好的负载平衡,同时保持他们在一起排序的扫描目的。这可以通过在该行的末尾附加一个随机的子串:
com.google.code_00
com.google.code_01
com.google.code_02
com.google.labs_00
com.google.mail_00
com.google.mail_01
它也可以通过添加一个字符串表示的一段时间,如一周或一个月的日期:
com.google.code_201003
com.google.code_201004
com.google.code_201005
com.google.labs_201003
com.google.mail_201003
com.google.mail_201004
追加日期提供了一个给定的日期范围限制扫描的附加功能。
7.3。索引
为了支持通过查找一个实体的多个属性,额外的索引可以建。然而,因为Accumulo表可以支持任意数量的列不事先指定的一个附加指标往往会在主表中的记录足以支持查找。在这里,该指数已为ROWID值或期限从主表,列的家庭都是一样的,预选赛的索引表列包含从主表的ROWID。
Term
Field Name
MainRowID
注:我们存储的rowid列预选赛,而不是价值,这样我们就可以有一个以上的ROWID与一个特定的期限内的指数相关。如果我们存储这个值,我们只能看到一个值出现自Accumulo默认配置为返回一个最新的值与键关联的那些行。
然后,可以通过先扫描索引表出现需要的值在指定的列,返回一个列表,从主表行ID查找。这些可以被用于检索每个匹配的记录,在他们的全部,或列的一个子集,从主表。
支持高效查找多个从同一个表的rowid中,Accumulo客户端库提供一个BatchScanner。用户可以指定一组范围,在多个线程执行的查找到多个服务器,并返回一个Iterator所有检索的行BatchScanner。返回的行排序顺序,不作为的情况下,基本的扫描仪接口。
// first we scan the index for IDs of rows matching our query
Text term = new Text("mySearchTerm");
HashSet<Text> matchingRows = new HashSet<Text>();
Scanner indexScanner = createScanner("index", auths);
indexScanner.setRange(new Range(term, term));
// we retrieve the matching rowIDs and create a set of ranges
for(Entry<Key,Value> entry : indexScanner)
matchingRows.add(new Text(entry.getKey().getColumnQualifier()));
// now we pass the set of rowIDs to the batch scanner to retrieve them
BatchScanner bscan = conn.createBatchScanner("table", auths, 10);
bscan.setRanges(matchingRows);
bscan.fetchFamily("attributes");
for(Entry<Key,Value> entry : scan)
System.out.println(entry.getValue());
动态模式的Accumulo能力的优点之一是,不同的字段可以采集到同一物理表。但是,它可能有必要建立不同的索引表,如果不同的条款必须进行格式化,以保持适当的排序顺序。例如,实数必须比自己平时的符号不同的格式,以正确排序。在这些情况下,通常独特的数据类型的每一个索引就足够了。
7.4。实体属性和图形表
Accumulo是理想的存储实体及其属性的属性,特别是稀疏。它往往是一起加入多个数据集,在同一表常见的实体。这可以允许的代表性的曲线图,其中包括节点,它们的属性,并且它连接到其他节点。
存储个别事件,而非实体的属性或图形表存储聚合信息的事件中所涉及的实体和实体之间的关系。单一事件时,不是非常有用,当随意一个不断更新的聚合,这通常是可取的。
实体 - 属性或图形表的物理架构如下:
EntityID
Attribute Name
Attribute Value
Weight
EntityID
Edge Type
Related EntityID
Weight
例如,要跟踪员工,经理和产品以下实体属性表可以使用。注意所用的权并不总是必要的,被设置为0时,不使用。
RowIDColumn FamilyColumn QualifierValueE001
name
bob
0
E001
department
sales
0
E001
hire_date
20030102
0
E001
units_sold
P001
780
E002
name
george
0
E002
department
sales
0
E002
manager_of
E001
0
E002
manager_of
E003
0
E003
name
harry
0
E003
department
accounts_recv
0
E003
hire_date
20000405
0
E003
units_sold
P002
566
E003
units_sold
P001
232
P001
product_name
nike_airs
0
P001
product_type
shoe
0
P001
in_stock
germany
900
P001
in_stock
brazil
200
P002
product_name
basic_jacket
0
P002
product_type
clothing
0
P002
in_stock
usa
3454
P002
in_stock
germany
700
为了有效更新的边权重,合计迭代器可以配置相同的密钥应用的所有突变添加值。这些类型的表可以很容易地创建从原始事件,个别事件的实体,属性和关系通过简单的提取和插入钥匙进入Accumulo各计数1。聚合迭代会照顾保持边缘权重。
7.5。文件分区索引
用一个简单的索引如上所述运作良好时,寻找匹配的记录一组给定的标准之一。同时符合多个条件的记录,如寻找文件包含所有的话时,当寻找'和'白'和'家',有几个问题。
首先是必须被发送到客户端,这会导致网络流量的特定匹配的搜索条件中的任一项,该组的所有记录。第二个问题是客户端是负责执行的交集上套的记录返回,以消除所有,但所有搜索条件匹配的记录。内存的客户端可能会在此操作过程中很容易被淹没。
由于这些原因,Accumulo包括支持的方案被称为分片索引,这些组操作可以被执行上面的TabletServers决定哪些记录包括在结果集中的,可以在不产生网络流量。
这是通过分割记录成箱,每个驻留在至多一个TabletServer上,然后创建一个索引,每个记录在每个垃圾桶如下:
RowIDColumn FamilyColumn QualifierValueBinID
Term
DocID
Weight
由用户定义的摄取应用映射到文件或记录。存储BinID的ROWID,我们确保特定斌的所有信息都包含在一个单一的平板电脑,并托管在一个单一的TabletServer以来从未分裂Accumulo行跨片。存储列家庭服务条款,使在这个垃圾桶的所有文件包含给定的长期快速查找。
最后,我们进行交集操作,通过一个特殊的迭代器称为相交迭代TabletServer。由于文件分割成许多垃圾桶,搜索所有文件必须搜索每一个垃圾桶。我们可以使用BatchScanner,并行扫描所有的垃圾桶。相交迭代器应该启用一个BatchScanner在用户查询代码如下:
Text[] terms = {new Text("the"), new Text("white"), new Text("house")};
BatchScanner bs = conn.createBatchScanner(table, auths, 20);
IteratorSetting iter = new IteratorSetting(20, "ii", IntersectingIterator.class);
IntersectingIterator.setColumnFamilies(iter, terms);
bs.addScanIterator(iter);
bs.setRanges(Collections.singleton(new Range()));
for(Entry<Key,Value> entry : bs) {
System.out.println(" " + entry.getKey().getColumnQualifier());
}
此代码有效的BatchScanner扫描一个表的所有平板电脑,寻找符合所有条款的文件。因为所有的平板电脑正在扫描的每个查询,每个查询比其他的Accumulo扫描,这通常涉及少数TabletServers更加昂贵。这减少了支持的并发查询数量和被称为'掉队'的问题,其中每一个查询运行慢最慢的服务器参与。
当然,快速的服务器将其结果返回给客户端,它可以显示给用户,而他们等待的结果到达其余立即。如果结果是无序的,这是一个相当有效的到达第一的成绩不如其他任何用户。
8。高速摄取
accumulo经常被用来作为一个更大的数据处理和存储系统的一部分。涉及Accumulo,摄取和查询组件的并行系统性能发挥到极致的设计应提供足够的并行和并发性,以避免产生瓶颈,为用户和其他系统写入和读取Accumulo。有几种方法,以实现高接收性能。
8.1。预拆分新表
新表包括默认情况下,一个单一的平板电脑。由于基因突变,表的增长和分裂成平衡由主跨TabletServers的多个片。这意味着总的摄取率将被限制在更少的服务器为群集内的,直到表中已经到了有是在每个TabletServer片其中。
预分割表,确保有尽可能多片随意摄取前开始利用一切可能的并行集群硬件。表可以随时拆分使用shell:
user@myinstance mytable> addsplits -sf /local_splitfile -t mytable
就提供并行摄取的目的,没有必要创造更多的平板电脑比有物理机集群内合共摄取率是一个函数的物理机数量。请注意,合共摄取率仍然摄取客户的机器上运行的数量,分布的rowid桌子对面的。的聚集摄取率将是次优的,如果有许多插入一个小数目的rowid。
8.2。多个Ingester客户端
Accumulo是能够扩展的摄取率非常高,这是取决于有多少人TabletServers运转中,但也摄取客户的数量。这是因为单个客户端,同时能配料突变和将它们发送到所有TabletServers,是最终在一台机器可以处理的数据的量限制。合共摄取率的客户端数点在其中的总I / O的TabletServers或总的网络带宽容量达到线性扩展。
在高利率的摄取是最重要的操作设置,群集通常配置仅运行Ingester客户奉献一定数量的机器。客户最佳的摄食率必要TabletServers,精确的比率会有所不同,根据每台机器的资源和数据类型的分布。
8.3。大量摄取
Accumulo支持的能力,如MapReduce的外部进程所产生的文件导入到现有的表。在某些情况下,它可能会更快加载数据,这种方式通过通过客户使用BatchWriters摄入而非。这使得大量的机器格式化数据的方式Accumulo预期。的新文件,然后简单地介绍到Accumulo通过一个shell命令。
要配置的MapReduce准备批量加载数据格式化,作业应设置使用范围分区工具,而不是默认的哈希分区工具。范围分区工具使用分割点的Accumulo表,将接收到的数据。分割点,可从外壳由MapReduce RangePartitioner的使用。请注意,这仅仅是有用的,如果现有的表已经分裂成多个片。
user@myinstance mytable> getsplits
aa
ab
ac
...
zx
zy
zz
运行MapReduce作业,使用创建文件的AccumuloFileOutputFormat被介绍给Accumulo的。一旦完成,文件可以添加到Accumulo通过壳:
user@myinstance mytable> importdirectory /files_dir /failures
需要注意的是引用的路径是目录,Accumulo运行在同一个HDFS实例。Accumulo将没有任何文件被添加到指定的第二个目录。
一个完整的例子,可以发现在使用大量摄取 accumulo /文档/例子/ README.bulkIngest
8.4。散装摄取的逻辑时间
逻辑的时间是非常重要的大宗进口数据,客户端代码可能会选择一个时间戳。在批量导入时,用户可以选择被导入文件的集合时间,以使逻辑。当它的启用,Accumulo使用迭代次批量导入的文件中懒洋洋地设置一个专门的系统。这种机制确保了时间不同步多节点应用程序(如运行MapReduce的)将保持一定的因果顺序的假象。这减轻了问题的时间是错误的系统上创建该文件批量导入。导入该文件时,这些时间都没有设置,但只要它是读取扫描或压实。进口,在一段时间内获得和总是使用由专门的系统迭代设置时间。
的时间戳分配的accumulo将在该文件中的每一个键是相同的。这可能会导致问题,如果文件中包含多个密钥是相同的时间戳除外。在这种情况下,按键的排序顺序是不确定的。这可能发生,如果在同一批量导入文件插入和更新。
8.5。MapReduce��摄取
这是可能的,以有效地写入许多突变Accumulo的平行的方式从一个MapReduce作业。在这种情况下被写入MapReduce的数据处理,住在HDFS中,写突变Accumulo使用AccumuloOutputFormat的。见的MapReduce下节分析的详细信息。
使用MapReduce的一个例子可以找到根据accumulo/docs/examples/README.mapred