我想就如何设计hbase表/行键以实现高效搜索提出建议
下面是一个示例数据集:
| Column Families | Column Qualifiers | Row 1 | Row 2 | Row 3 |
---------------------------------------------------------------------------------------------------------
| Country | Code | US | | UK |
|
| | Full Name |United States of America| |United Kingdom |
| | Capital |Washington, DC | |London |
| | Leader | President | President |Prime minister |
|State | | Texas | | |
|District | |Houston |LA | |
|County | |Harris |Harris | Cambridge |
|City | |Houston city |Duke City | |
|Road | |Bellare | |Downing Street |
|Family | |Doe |Wade | |
|Person | Name |John Doe |Doo |Smith |
| | Location |35.00 N, 99.00 W |31.00 N , 100.00 W | |
| | Gender | |Female |Male |
| | Religion |Atheist |Maya |Christian |
注意:在上面的示例数据集中,列限定符只针对第一个和最后一个列族进行了详细说明,以避免数据混乱。
数据概述:这是一个分层数据集,但任何级别的信息都可能丢失例如,第2行没有国家信息第3行,英国没有国家的概念,因此英国的记录将丢失国家分层
要求搜索以下场景:
|Search Criteria |Returned Records |
-----------------------------------------------------------------
|All records |3 count, Row1, Row2 & Row3 |
|Country = USA |1 Record, Row 1 |
|Gender = Male |1 Record, Row 3 |
|County = Harris |2 records, Row 1 & Row 2 |
|LATITUDE > 30 and LONGITUDE < 101 |2 records, Row 1 & Row 2 |
|All Atheist for USA |1 record, Row1 |
拟定设计方案:
1. 为每个级别创建八列族,因为可以添加需要在每个级别搜索的信息(例如,领导姓名、职位、时区、级别的地区、市、县、区、国家等)
|Level one |Country |
|Level two |State |
|Level three |District |
|Level four |County |
|Level Five |City |
|Level Six |Road |
|Level Seven |Family |
|Level Eight |Person |
将rowkey设计为复合键,这是所有级别代码的组合,因为搜索可以在任何级别1上进行code:level2code:级别3code:level4code:级别5code:level6code:级别7code:level8code:例如,美国:101:102:103:104:105:106:107
我正在考虑的另一种选择是创建一个二级索引,但由于我计划使用hbase作为我的web应用程序的后端,因此必须在性能方面进一步研究它。
提前感谢您分享您的专业知识!
1条答案
按热度按时间t98cgbkg1#
关于列族的数量,我坚持使用尽可能少的族(hbase docs)。考虑到你的情况,我会尝试使用两个族:一个用于位置数据,另一个用于与人相关的数据,这样你就可以按位置搜索,而不必阅读任何有关此人的信息,反之亦然。只是提醒一下,如果你只扫描一个家庭来加快速度,你只能检索该家庭的数据,因此在这种情况下,如果你在我们内部寻找人,你将无法得到他们的名字,除非你还添加了其他家庭,如果是这样的话,拥有多个家庭没有任何好处。如果您的数据需要不同的配置(ttl、版本、压缩…),或者可以独立查询而不需要来自其他族的数据,则可以使用多个族。
最后,这完全取决于最常见的查询以及何时需要减少读取的数据量:假设您根据地理位置执行许多查询,在这种情况下,我会将lat和long列移动到它们自己的族中,以避免读取任何其他内容。
关于复合行键:我不太确定levelcode id来自何处,它们是不是存储在其他地方的标准化值?。如果将行键作为字符串存储在行键中,则行键看起来相当大(任何字符都将占用1字节,如果levelcode id较大,则以+60字节的行键结尾),请注意,在hbase中,每个单元格都包含行键+列族+列+时间戳+值,因此,就存储而言,这将是一个相当大的开销,在查询时不会有太多性能提升。
如果您的levelcode id是规范化的整数,并且您想使用它们来过滤数据,那么您应该考虑添加一个ids系列(值作为整数列),这样您就可以只扫描该系列并过滤掉不需要的数据
SingleColumnValueFilter
.如果您有一些空闲时间,可以看看amandepkhurana对hbase模式设计的伟大介绍。
关于实时答案
如果您需要为您的查询提供实时答案,那么在给定大量数据的情况下,这两种方法都不能很好地工作。hbase是一个数据存储,而不是一个搜索引擎,它可以在巨大的数据集中运行搜索和分析作业,但它们不会是实时的。
通过适当的设计,hbase可以作为简单搜索的实时后端,但在设计表时应遵循以下原则:
不惜一切代价避免完全扫描,即使他们有过滤器。全扫描=读取每一行=不适合实时。
写得很快。反规范化并根据需要写入尽可能多的数据,以加快数据检索。
这意味着,如果需要实时检索查询,则需要为预期运行的每个查询提供二级索引。所有的扫描查询都应该至少有一个起始行键,这就要求将相同的数据写入不同行键下的多个表(或者甚至通过为每个索引类型使用前缀写入同一个表,我不建议这样做,这会使拆分非常困难,并且可能会出现热点问题)。
请注意,您的一些查询组合了多个字段(“all atheist for usa”或“latitude>30 and longitude<101”),在这些情况下,您还需要为它们和它们的每个组合创建一个辅助索引,如果您想用hbase处理它们,这将使事情变得更加复杂。
我倾向于不建议切换到其他系统,因为通常情况下,事情可以或多或少地完成,但是,基于您的用例,我认为最好选择一个搜索引擎,它自己负责索引。
也许你会发现elasticsearch对你的任务很有用:它快速、易学、灵活、可靠、可伸缩,并且在许多语言中都有很好的api。