3

为了更好地说明这个问题,我将从一个例子开始。可以说,您有 3 张桌子:

  • 学生(200 万行)
  • 测试结果(1 亿行)
  • 测试(100 000 行)。

我们将所有相关数据分组并添加一个名为“TestSynthesis”的非规范化表,其中包含一个键:TestID_StudentID_TestResultsID。键中字段的顺序无关紧要,因为用户需要能够通过该键的三个部分中的任何一个或全部进行搜索。

一个示例查询是:“给我所有名字以‘约翰’开头的学生的所有测试结果”

一个简单的解决方案是:

  1. 搜索标准化表学生
  2. 提取 StudentID(假设我们有 3 个 id:0001000,0000999,0000001)
  3. 然后在这些 id 上搜索 TestSynthesis (如 * 0001000 * , * 0000999 * , * 0000001 *)

但是如果在第 2 步,我们得到 100 万行而不是 3 个学生呢?

HBase 可以只搜索键(例如不读取数据),还是需要进行全表扫描?

4

1 回答 1

14

首先是痛苦的事实。正如其他帖子中提到的,HBase 不完全支持部分键。正如您所提到的,假设您通过以下方式获得密钥:TestID_StudentID_TestResultsID

您无法通过 StudentID 进行搜索,同时享受出色的性能。但是,有一种方法可以在扫描期间过滤行,仅取决于行键。但请记住,过滤器的性能比良好的优化表模式更差。因此,出于理解/经验,您有以下选择:

1)您尝试设计方案,使其针对大量查询进行优化。例如,大多数查询都需要给定学生的数据,因此您将 studentID 放在键的开头。有些查询需要知道当前学生的测试结果,然后您使用 {STARTROW=>given_studentID, STOPROW=>given_studentID+1} 进行扫描,并使用 keyfilters 过滤您获得的结果。可以设置 keyfilters 来过滤特定的 testID。但是在这种情况下,如果您想查看哪些学生参加了测试,则需要进行全面扫描并对结果集应用过滤器,当我们谈论性能时,这并不是很“便宜”。

2) 正如 [http://stackoverflow.com/questions/12806762/hbase-data-only-in-key-compoung-key-wildcards][1] 中所建议的,您还可以将数据复制到两个不同的表中,第一个是 TestID_StudentID_TestResultsID,第二个是这样的:StudentID_TestID_TestResultsID。通过这种方式,您可以通过给定的 testID 或 StudentId 进行查询,因为您可以在第一个或第二个表中愉快地搜索。如果您想知道哪个学生在所有测试中获得最佳结果,那么您再次遇到麻烦。在这种情况下,您再次需要进行全面扫描。了解您将要进行什么样的查询非常重要,这样您就可以适当地规划您的模式。(无论如何,您真的需要密钥中的测试结果吗?)

3)还有第三种选择,我用过一次。这在很大程度上取决于数据本身。假设您将有 500 000 个学生,大约 50 个测试,然后是 50*500 000 个测试结果。在这种情况下,我将按以下方式设计架构:TestID_StudenIT_Results

*如果您想查看学生在特定测试中的表现,您可以根据测试进行扫描,因为密钥以它开头。

*如果您想查看学生在所有测试中的表现,您可以进行 50 次扫描,每次扫描都使用 50 个 testID 中的一个,以便扫描看起来像:

test1_studentX

test2_studentX

test3_studentX

test4_studentX

...

...

test50_studentX

50 次扫描可能听起来太多,但它非常适合地图缩减工作。问题来了,你真的有 50 个 testID,还是你拥有的数字适合这个?

*如果您想查看所有学生在所有测试中的表现,您仍然需要使用此模式进行全面扫描。

那是我的!

干杯,尼科

于 2012-10-20T13:17:05.810 回答