数据查询的玄铁剑:阿里云HBase二级索引功能解析

简介: HBase原生提供了主键索引,用户可以根据rowkey进行高效的单行读、前缀匹配、范围查询操作。但若需要使用属性列进行查询时,则只能使用filter在查询范围内进行逐行过滤。在扫描范围较大时,会浪费大量的IO,请求RT也无法保证。为此,HBase增强版推出了原生二级索引来解决非rowkey查询的性能问题。

HBase用户福利

新用户9.9元即可使用6个月云数据库HBase,更有低至1元包年的入门规格供广大HBase爱好者学习研究,更多内容请参考链接

前沿

HBase原生提供了主键索引,用户可以根据rowkey进行高效的单行读、前缀匹配、范围查询操作。但若需要使用属性列进行查询时,则只能使用filter在查询范围内进行逐行过滤。在扫描范围较大时,会浪费大量的IO,请求RT也无法保证。为此,HBase增强版推出了原生二级索引来解决非rowkey查询的性能问题。

云HBase增强版是基于阿里内部的HBase分支(亦称Lindorm)构建的,二级索引是其核心能力之一,历经多年双11大考,在性能、吞吐、稳定性等方面都具备核心竞争力。

下面,我们从一组示例出发来了解索引的使用及其能力。

功能简介

从表设计和查询设计的角度看,HBase增强版二级索引的使用与RDBMS的二级索引基本一致。下面我们看一个简单的示例:大学生信息表(Students),该表的主键(即rowkey)是学号,非主键是学生姓名和所属的学院名称。学生与学院是多对一的关系。

通过HBase shell建表,建索引:

# 创建主表student,列族名为f
create 'student', 'f'

# 创建索引表department,为department列建索引
# COVERED_ALL_COLUMNS是HBase增强版引入的新属性关键字,
# 意味冗余主表student中的所有列,以此来避免回查主表
create_index 'department', 'student', {INDEXED_COLUMNS => ['f:departement']}, {COVERED_COLUMNS => ['COVERED_ALL_COLUMNS']}

通过Java API进行数据访问

// 定义一些常量
String id = "11";   // 一个随机的学号
String studentName = "Harry";
String department = "CS";
byte[] f = Bytes.toBytes("f");
byte[] qStudent = Bytes.toBytes("name");
byte[] qDepartment = Bytes.toBytes("department");

// 写入一个学生的数据
Put put = new Put(Bytes.toBytes(id));
put.addColumn(f, qStudent, Bytes.toBytes(studentName));
put.addColumn(f, qDepartment, Bytes.toBytes(department));
Table t = conn.getTable("student");
t.put(put);         // put成功返回意味着主表和索引表都成功更新,变更立即可见

// 按department进行查询
Scan scan = new Scan();
SingleColumnValueFilter where = new SingleColumnValueFilter(
    f, qDepartment, EQUAL, Bytes.toBytes(department));
scan.setFilter(where);
ResultScanner rs = t.getScanner(scan);
// 处理查询结果...

从上例可见,用HBase API直接描述查询请求即可使用索引。HBase增强版会自动根据filter以及索引schema来匹配到最合适的索引进行查询,必要时,在查完索引后也会回查主表(上例中,如果不是全冗余索引,则会回查主表来补全列)。更多使用上的说明请参考二级索引开发手册

HBase增强版二级索引的主要特性有:

  • 支持为单个主表建多个索引
  • 支持单列和多列索引(组合索引)
  • 支持冗余索引:可显式指定冗余列,或冗余所有列,避免回查主表的性能损耗
  • 查询优化:根据scan和filter自动选择合适的索引表进行查询,必要时会自动回查主表
  • online schema change:支持给已经在使用的表建索引,对主表读写无影响
  • 支持TTL:索引表会自动继承主表的TTL,主表和索引表数据一起过期
  • 支持自定义数据版本:用户自定义数据时间戳写入(暂未开放)

产品优势

高性能

HBase增强版二级索引直接内置于内核中,并做了深度优化,提供了强大的吞吐与性能。下图是HBase增强版二级索引与Apache Phoenix的全局索引的性能对比:

gsi_pr_perf

从上图可见,无论RT还是吞吐,HBase增强版二级索引均远超Apache Phoenix。

写后可读

数据写入返回成功后,则索引数据可立即被读到,消除传统异步建索引方案中的数据延迟,提供具有一定程度的强一致性语义(主表和索引表的数据一致性),具体语义如下:

  • 返回客户端写入成功,之后可立即读到刚写入的数据(包括主表和索引数据);写入过程中不保证同时可见
  • 返回超时或IO出错,则在一段时间内,该数据在主表和索引表中的可见性无法确定,但保证最终一致,即要么全成功,要么全不成功

HBase增强版提供的”写成功后更新立即可见的语义“,可用于一些分布式协同的任务,比如spark,在某些节点更新数据,另外一些节点读取上一轮计算写入的数据。此时,一定可以读到刚写入的数据。

全冗余索引

全冗余索引可彻底避免回查主表,提升性能;同时也是语法糖,避免手工维护复杂的DDL。下面分别介绍。

如果查询中需要的列在索引表中没有,则查完索引后,还需回查主表。在分布式场景下,回表查询会使得查询RT大幅度升高,最差情况下可能会回查主表的全部region,访问集群中的所有机器。此时,索引带来的性能收益已经可有可无。通过精良的查询设计和索引设计,我们可以在设计阶段避免回查,但随着业务发展变化,这个约束很难维持。因此,仍然需要冗余索引(Covered Index)来解决。

HBase增强版创造性的引入了全冗余索引的概念,即冗余主表中的所有列,以此来彻底避免回查主表。配合HBase的schema-free特性,主表中新增的任何列都会自动冗余到索引表中。无论业务模式如何变化,都不需要回查主表。

同时,全冗余也是可大幅度提升效率的语法糖,我们可以对比如下两个SQL语句:

CREATE INDEX idx ON dt (c1, c2) include(c3, c4, c5, c6, ....);
CREATE INDEX idx ON dt (c1, c2) include(ALL);

对于大部分业务来说,表里有数十列是常态,个别表可能会有数百列。如果为了建冗余索引,而把这数百列的列名再写一遍,无疑是巨大的负担(只能写工具自动化做,人来做太容易出错)。全冗余索引的新语法给人工维护DDL提供了可能。

为了获得上述两点收益,全冗余索引的代价是会占用更多存储空间。配合HBase增强版深度优化的ZStandard压缩算法,可有效降低冗余带来存储开销。冷热分离特性亦可应用于索引表,进一步控制成本。

基于原生API的查询优化

对大部分场景来说,业务一行代码不改就能用上索引。

从本文开头的示例代码中可见:

  • 写:写主表即可,会自动同步到索引,强一致。用户无需担心索引更新的问题
  • 读:基于主表进行查询,直接按业务逻辑进行查询表达,系统自动选择合适的索引表进行查询

这样,用户只需为那些性能不好的查询设计并添加索引,即可从索引特性中受益,实际的数据读写代码一般不需要修改。同时,既有的HBase生态相关的产品,都可以无缝使用上索引。一些如Spring的框架软件也可帮助用户获得业务上的灵活性。

大表建索引

从一开始就设计好主表和全部索引几乎是不可能的。因此,在后续业务发展过程中,索引表可能需要不断的删除和新增。为此,对一个已经有大量数据表添加、删除索引,将是一个关键的运维操作。HBase增强版二级索引针对此场景做了特别的优化:

  • schema在线修改:索引的变更不影响主表的正常读写(就像一次普通的alter表操作),不影响其他索引表
  • 服务端rebuild:在服务端为主表的历史数据构建索引
  • 支持对超大主表添加索引:支持TB级别的主表添加新索引
  • 流控:大主表的索引rebuild会消耗大量的系统资源,因此,精准的流控即可在兼顾索引构建速度的前提下,保障系统整体性能不会被影响

在有上述特性的加持下,索引变更的运维成本和风险大大降低,从容的适应业务发展。

原理简介

HBase增强版二级索引是一种全局二级索引,每个索引表都是一张独立的HBase表。每张表的主键(rowkey)设计决定了其能支持的查询模式。当同一份数据有多种rowkey组织时,就能支持多种查询模式。这里,主表和它的索引表,可以看做是同一份数据的不同组织形式,各自能够高效的支持一定的查询模式。
考虑本文开始时给出的学生信息表的示例:

gsi_pr_schema

主表Student:以学号(id)为主键(rowkey),每行有两列,学生姓名(name)和所属的学院(department)。该设计仅支持按id进行查询。如果用户要按department或者name来查询,需要全表扫描 + filter。在学生数较少时,这种暴力扫描完全可行。但在数据量大时(数十万乃至上亿时),这种操作是无法执行的。

为了高效的支持按department查询,可为其建立一个全冗余索引(使用HBase shell):

create_index 'department', 'student', {INDEXED_COLUMNS => ['f:departement']}, {COVERED_COLUMNS => ['COVERED_ALL_COLUMNS']}

在建索引时,系统会自动为主表中的存量数据构建索引,写入索引表中。主表行和索引行是一一对应的。之后主表上发生的数据更新,也会自动同步给索引表。
考虑如下查询:

-- 查找所有计算机学院(cs)的学生的姓名(name)
select name from student where department = 'cs';

这个查询会直接命中索引表,按department列进行前缀匹配。从每一个索引行中提取name字段,返回给客户端。

如果我们没有建立冗余索引,则索引表中不会存在name列。此时,在从索引表中读取到学号(id)后,必须回查主表(三次按id的单行读)来读取name列。在分布式场景下,10/12/13这三个id的数据可能分布在三台机器上。因此,回查主表最差情况下需要3次RPC,加上查索引表的一次RPC,共需4次RPC。而如果是冗余索引,则只需查索引表的一次RPC即可。

因此,在分布式场景,尤其是节点很多的大集群,回查主表带来的性能损耗是巨大的(RT可能会增长数倍)。这也是我们设计全冗余索引的初衷:避免回查,提高性能。

总结

数据只有被查询才能创造价值,HBase原生高性能二级索引为多维度查询提供了一种有效的解决方案。在表设计上,用户可以参考MySQL等关系型数据库的索引设计思路来进行HBase的索引设计。业务无需更改代码,查询优化可自动进行索引表的选择。强一致、全冗余索引等特性也有效降低了业务的使用门槛。
未来,我们将对索引做进一步的优化和扩展,提供优质的用户体验。欢迎大家体验HBase增强版。如您有对HBase相关的任何问题,欢迎通过钉钉与我们联系(钉钉搜索“云HBase值班”)。

相关链接

HBase技术交流

欢迎加群进一步交流沟通:
image.png
image.png

相关实践学习
lindorm多模间数据无缝流转
展现了Lindorm多模融合能力——用kafka API写入,无缝流转在各引擎内进行数据存储和计算的实验。
云数据库HBase版使用教程
  相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情: https://cn.aliyun.com/product/hbase   ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1月前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
173 9
|
6天前
|
搜索推荐 UED Python
实现一个带有昼夜背景切换的动态时钟:从代码到功能解析
本文介绍了一个使用Python和Tkinter库实现的动态时钟程序,具有昼夜背景切换、指针颜色随机变化及整点和半点报时功能。通过设置不同的背景颜色和随机变换指针颜色,增强视觉吸引力;利用多线程技术确保音频播放不影响主程序运行。该程序结合了Tkinter、Pygame、Pytz等库,提供了一个美观且实用的时间显示工具。欢迎点赞、关注、转发、收藏!
122 94
|
17天前
|
Serverless 对象存储 人工智能
智能文件解析:体验阿里云多模态信息提取解决方案
在当今数据驱动的时代,信息的获取和处理效率直接影响着企业决策的速度和质量。然而,面对日益多样化的文件格式(文本、图像、音频、视频),传统的处理方法显然已经无法满足需求。
70 4
智能文件解析:体验阿里云多模态信息提取解决方案
|
3天前
|
存储 运维 安全
深入解析操作系统控制台:阿里云Alibaba Cloud Linux(Alinux)的运维利器
本文将详细介绍阿里云的Alibaba Cloud Linux操作系统控制台的功能和优势。
23 5
|
6天前
|
人工智能 自然语言处理 搜索推荐
销售易、悟空、神州云动CRM:全方位功能解析与优势特色盘点
销售易CRM、悟空CRM和神州云动CRM各自具备独特的产品功能与优势,适用于不同类型的企业。销售易CRM提供移动化、社交化和AI驱动的全流程管理,适合大型企业及跨国公司;悟空CRM以智能数据分析和移动办公支持见长,适合中大型企业;神州云动CRM则凭借灵活定制和多行业适配能力,特别适合大中型企业。企业在选择时应根据自身需求和发展战略,挑选最适合的CRM系统,以实现客户关系管理的最大化效益。
|
26天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
18天前
|
存储 物联网 大数据
探索阿里云 Flink 物化表:原理、优势与应用场景全解析
阿里云Flink的物化表是流批一体化平台中的关键特性,支持低延迟实时更新、灵活查询性能、无缝流批处理和高容错性。它广泛应用于电商、物联网和金融等领域,助力企业高效处理实时数据,提升业务决策能力。实践案例表明,物化表显著提高了交易欺诈损失率的控制和信贷审批效率,推动企业在数字化转型中取得竞争优势。
74 14
|
18天前
|
存储 数据库 对象存储
新版本发布:查询更快,兼容更强,TDengine 3.3.4.3 功能解析
经过 TDengine 研发团队的精心打磨,TDengine 3.3.4.3 版本正式发布。作为时序数据库领域的领先产品,TDengine 一直致力于为用户提供高效、稳定、易用的解决方案。本次版本更新延续了一贯的高标准,为用户带来了多项实用的新特性,并对系统性能进行了深度优化。
28 3
|
19天前
|
供应链 数据可视化 数据挖掘
企业服务品牌深度解析:销售易、用友、白码功能与特色对比
在企业服务领域,销售易、用友、白码等品牌凭借独特的产品和解决方案占据重要地位。销售易专注于CRM,提供客户管理、销售自动化、市场营销等功能,提升销售效率与客户满意度。用友作为领先的企业服务提供商,涵盖ERP、财务管理、人力资源管理等,助力企业资源优化配置。白码则以低代码开发平台为核心,支持快速构建业务应用,具备高度可定制化和易于维护的特点。三者各具特色,共同推动企业数字化转型。
|
4月前
|
分布式计算 Java Hadoop
java使用hbase、hadoop报错举例
java使用hbase、hadoop报错举例
135 4

热门文章

最新文章

相关产品

  • 云数据库HBase版
  • 推荐镜像

    更多