我正在学习Accumulo,似乎无法获取范围中包含的范围内指定的结束键。我的代码如下。我尝试将endKeyInclusive
中的true
设置为Range
,但这没有帮助。
BatchWriter writer = conn.createBatchWriter("table", config);
List<String> deterTimes = new ArrayList<>();
String rowId = "3015551212<ll>";
String columnFamily = "deter";
for (int i = 0; i < 10; i++) {
String deterTime = "20181112:21:46:33" + i;
deterTimes.add(deterTime);
writer.addMutation(makeRecord(rowId, columnFamily, deterTime, "DETER" + i));
}
writer.flush();
writer.close();
Scanner scan = conn.createScanner("table", auths);
Key startKey = new Key(rowId.getBytes(), columnFamily.getBytes(), deterTimes.get(1).getBytes());
Key endKey = new Key(rowId.getBytes(), columnFamily.getBytes(), deterTimes.get(4).getBytes());
Range range = new Range(startKey, endKey);
if (range.isEndKeyInclusive()) System.out.println("true");
scan.setRange(range);
for (Entry<Key,Value> entry : scan) {
Text row = entry.getKey().getRow();
Text cq = entry.getKey().getColumnQualifier();
Value value = entry.getValue();
System.out.println("Fetched row " + row + " with value: " + value + ", cq=" + cq);
}
输出:
true
Fetched row 3015551212<ll> with value: DETER1, cq='20181112:21:46:331'
Fetched row 3015551212<ll> with value: DETER2, cq='20181112:21:46:332'
Fetched row 3015551212<ll> with value: DETER3, cq='20181112:21:46:333'
答案 0 :(得分:1)
您将使用( row, column family, column qualifier )
作为字节数组来构造结束键,并且将键( column visibility, timestamp )
的其余维设置为默认值(分别为空字节数组和Long.MAX_VALUE
)。
扫描仪将停止在该确切键处(包括端点值)。但是,您实际输入的数据几乎肯定不是那个 exact 键(您没有提供makeRecord
的实现来进行验证)。即使您的数据实际上具有空的列可见性,时间戳也几乎肯定不是Long.MAX_VALUE
,而是您在makeRecord
实现中设置的时间戳,或者它是根据tserver的时间或某些表逻辑计数器设置的。由于密钥的时间戳维是按降序排列的,因此扫描仪将在到达输入之前在Long.MAX_LONG
上停止查找数据。
这有点像在字典中搜索analogy
,但是到达analog
时便停止了:您会错过以analog
开头的其余单词。
基于精确键构造范围时,这是常见的陷阱。通常最好基于行(包括行将包括整个行)而不是键(存在Range
constructor for that)来构造范围。或者,指定结束键以使其独占工作。您可以通过在该列的最后一个有意义的元素的末尾附加一个空字节来做到这一点。例如,您可以执行以下操作:
Key endKey = new Key(rowId.getBytes(),
columnFamily.getBytes(),
(deterTimes.get(4) + "\0").getBytes());
Range range = new Range(startKey, true, endKey, false);
您应该注意的另一个陷阱是使用String.getBytes()
来获取字节数组,而不指定编码。最好使用一致的内容,例如"abc".getBytes(StandardCharsets.UTF_8)
(不过我通常会进行静态导入,因此我只能指定UTF_8
)。
答案 1 :(得分:0)
Range在此运行,但是添加的值可能存在问题
这将更易于通过输出进行诊断,但是您是否有可能期望将延迟时间提高一个,因为数组从零开始,因此您看到的deterTime比预期的时间少了一个?
如果不是这种情况,请分享您的输出