八、Hbase

时间:2024-12-20 13:56:44

Hbase

  • 一、NoSQL非关系型数据库简介
    • 1.NoSQL 的起因
    • 2.NoSQL 的特点
    • 3.NoSQL 面临的挑战
    • 4.NoSQL 的分类
  • 二、HBase数据库概述
    • 1.HBase数据库简介
    • 2.HBase数据模型简介
    • 3.HBase数据模型基本概念
    • 4.Hbase概念视图(逻辑视图)
    • 5.Hbase物理视图
    • 6.Hbase主要组件
    • 7.Hbase安装
    • 8.Hbase的数据读写流程
    • 9.Hbase的数据结构
    • 10.Hbase的rowkey设计
  • 三、Hbase Shell:DDL语句操作
  • 四、Hbase Shell:DML语句操作
  • 五、eclipse操作hbase
    • 1.开发环境配置
      • 1.配置pom.xml文件
      • 2.新建hbase-site.xml文件,放到资源文件目录下
      • 3.新建mapred-site.xml文件,放到资源文件目录下
      • 4.新建log4j.properties文件,放到资源文件目录下
    • 2.JAVA-HBASE:DDL操作
    • 3.JAVA-HBASE:DML操作
    • 4.JAVA-HBASE:DQL操作
    • 5.JAVA-HBASE:filter用法
  • 六、ORC文件转HFILE文件
    • 1.数据准备
    • 2.项目的整体架构
      • 1.配置文件
        • 1.配置pom.xml文件
        • 2.新建assembly.xml文件,放到资源文件目录下
        • 3.拷贝hbase-site.xml、文件,放到资源文件目录下
        • 4.拷贝mapred-site.xml文件,放到资源文件目录下
        • 5.拷贝log4j.properties文件,放到资源文件目录下
      • 2.com.shanhai.util
        • 1.BaseMR
        • 2.JobRunnerResult
        • 3.JobRunnerUtil
        • 4.MyConstant
        • 5.ORCFormat
        • 6.ORCUtil
        • 7.Utils
      • 3.com.shanhai.mr
        • 1.HbaseImportData
      • 4.com.shanhai.bin
        • 1.MyJobRunner
        • 2.MyJobDriver
    • 3.集群配置
    • 4.集群运行
  • 七、Hbase表的预分Region
    • 1.小批量预分Region
    • 2.大批量预分Region
    • 3.如何修改HBase表的压缩格式
  • 八、Hbase数据的批量导入+预分Region
    • 1.需求
    • 2.项目的整体架构
      • 1.配置文件
        • 0.新建split_data文件
        • 1.拷贝pom.xml文件
        • 2.新建assembly.xml文件,放到资源文件目录下
        • 3.拷贝hbase-site.xml、文件,放到资源文件目录下
        • 4.拷贝mapred-site.xml文件,放到资源文件目录下
        • 5.拷贝log4j.properties文件,放到资源文件目录下
      • 2.com.shanhai.util
        • 1.BaseMR
        • 2.JobRunnerResult
        • 3.JobRunnerUtil
        • 4.MyConstant
        • 5.MyRegionSpliter
        • 6.ORCFormat
        • 7.ORCUtil
        • 8.Utils
      • 3.com.shanhai.mr
        • 1.NewHbaseDataImport
      • 4.com.shanhai.bin
        • 1.NHIDJobRunner
        • 2.NHIDJobDriver
    • 3.集群环境配置
    • 4.集群运行
  • 九、HFILE文件转ORC文件
    • 1.HFILE-BY-ORC项目的整体架构
      • 1.配置文件
        • 1.新建assembly.xml文件,放到资源文件目录下
      • 2.com.shanhai.util
        • 6.ORCWriteUtil
      • 3.com.shanhai.mr
        • 1.HfileByOrc
      • 4.com.shanhai.bin
        • 1.HBORunner
        • 2.HBODriver
    • 2.集群运行
    • 3.创建Hive-ORC-外部表
    • 4.验证数据
  • 十、MR读写AVRO文件
    • 1.项目需求:
    • 2.生成测试数据
    • 3.项目的整体架构:
      • 1.com.shanhai.mr
        • 1.AvroToAvro
      • 1.com.shanhai.bin
        • 1.ATARunner
    • 4.线下运行:
    • 5.集群运行
  • 十一、Hbase数据的批量导出
    • 1.项目需求:
    • 2.项目的整体架构:
      • 1.配置文件
        • 1.pom.xml文件
        • 2.新建assembly.xml文件,放到资源文件目录下
      • 2.com.shanhai.util
        • 1.ORCWriteUtil
        • 2.HFileInputFormat:自定义输入格式化类
      • 3.com.shanhai.entity
        • 1.HFileItem
        • 2.HFileRecord
      • 4.com.shanhai.mr
        • 1.NewHbaseDateExport
      • 5.com.shanhai.bin
        • 1.NHDERunner
        • 2.NHDEDriver
    • 3.集群运行

一、NoSQL非关系型数据库简介

1.NoSQL 的起因

随着 Web 2.0 网站的兴起,传统的关系数据库已经无法适应 Web 2.0 网站,特别是超大规模和高并发的社交类型的 Web 2.0 纯动态网站;
NoSQL 数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
1. 无法满足对海量数据的高效率存储和访问的需求
2. 无法满足对数据库的高可扩展性和高可用性的需求
3. 关系数据库无法存储和处理半结构化/非结构化数据
4. 关系数据库的事务特性对 Web 2.0 是不必要的
5. Web 2.0 无须进行复杂的 SQL 查询,特别是多表关联查询

2.NoSQL 的特点

它所采用的数据模型并非关系型数据库的关系模型,而是类似键值、列簇、文档等的数据模型。它打破了长久以来关系型数据库与 ACID(原子性(Atomicity)、一致性(Consistency)隔离性(Isolation)和持久性(Durability))理论大一统的局面。
NoSQL 数据存储不需要固定的表结构,每一个元组可以有不一样的字段,每个元组可以根据需要增加一些自己的键值对,这样就不会局限于固定的结构,可以减少一些时间和空间的开销。
NoSQL 在大数据存取上具备关系型数据库无法比拟的性能优势。
1. 灵活的可扩展性
2. 大数据量和高性能
3. 灵活的数据模型,可以处理半结构化/非结构化的大数据

3.NoSQL 面临的挑战

NoSQL 数据库的前景很被看好,但是要应用到主流的企业还有许多困难需要克服。这里是几个首先需要解决的问题。
1. 成熟度(相比关系数据库系统来说,技术还不够成熟。这种状况会随着时间而改进)
2. 支持(需要资金来维持软件的开发和维护)
3. 分析与商业智能(NoSQL 数据库缺少即时查询和数据分析工具)
4. 管理(NoSQL 的设计目标是提供零管理的解决方案,不过当今还远远没有达到这个目标。)
5. 专业(大多数 NoSQL 开发者还处于学习模式。这种状况会随着时间而改进)

4.NoSQL 的分类

可以将典型的NoSQL 划分为 4 种类型,分别是键值数据库、列式数据库、文档数据库和图形数据库
1. 键值数据库:典型代表-->Redis
它使用一个哈希表,表中的 Key(键)用来定位 Value(值),即存储和检索具体的 Value2. 列式数据库:典型代表-->Hbase
列式数据库起源于 Google 的 BigTable,其数据模型可以看作是一个每行列数可变的数据表
3. 文档数据库:典型代表-->MongoDB
文档数据库是通过键来定位一个文档的,所以是键值数据库的一种衍生品。在文档数据库中,文档是数据库的最小单位。文档数据库可以使用模式来指定某个文档结构。
文档数据库是 NoSQL 数据库类型中出现得最自然的类型,因为它们是按照日常文档的存储来设计的,并且允许对这些数据进行复杂的查询和计算。
4. 图形数据库:典型代表--> Neo4J、OrientDB、InfoGrid、Infinite Graph 和 GraphDB 
图形数据库以图论为基础,用图来表示一个对象集合,包括顶点及连接顶点的边。图形数据库使用图作为数据模型来存储数据,可以高效地存储不同顶点之间的关系。
图形数据库是 NoSQL 数据库类型中最复杂的一个,旨在以高效的方式存储实体之间的关系。

二、HBase数据库概述

1.HBase数据库简介

HBase 是基于 Apache Hadoop 的面向列的 NoSQL 数据库,是 Google 的 BigTable 的开源实现。
HBase 是一个针对半结构化数据的开源的、多版本的、可伸缩的、高可靠的、高性能的、分布式的和面向列的动态模式数据库。
HBase 和传统关系数据库不同,它采用了 BigTable 的数据模型增强的稀疏排序映射表(Key/Value),其中,键由行关键字、列关键字和时间戳构成。
HBase 提供了对大规模数据的随机、实时读写访问。
HBase 的目标是存储并处理大型的数据,也就是仅用普通的硬件配置,就能够处理上千亿的行和几百万的列所组成的超大型数据库。
Hadoop 是一个高容错、高延时的分布式文件系统和高并发的批处理系统,不适用于提供实时计算,
而 HBase 是可以提供实时计算(占用大量的内存)的分布式数据库,数据被保存在 HDFS (分布式文件系统)上,由 HDFS 保证其高容错性。
HBase 上的数据是以二进制流的形式存储在 HDFS 上的数据块中的,但是,HBase 上的存储数据对于 HDFS 是透明的。
HBase 可以直接使用本地文件系统,也可以使用 Hadoop 的 HDFS。
HBase 中保存的数据可以使用 MapReduce 来处理,它将数据存储和并行计算有机地结合在一起。
HBase 是按列族进行数据存储的。每个列族会包括许多列,并且这些列是经常需要同时处理的属性。也就是说,HBase 把经常需要一起处理的列构成列族一起存放,从而避免了需要对这些列进行重构的操作。
HBase 在充分利用列式存储优势的同时,通过列族减少列连接的需求。

2.HBase数据模型简介

HBase 是一个稀疏、多维度、有序的映射表。
这张表中每个单元是通过由行键、列族、列限定符和时间戳组成的索引来标识的。
每个单元的值是一个未经解释的二进制数组(byte[]),没有数据类型。当用户在表中存储数据时,每一行都有一个唯一的行键和任意多的列。
表的每一行由一个或多个列族组成,一个列族中可以包含任意多个列。在同一个表模式下,每行所包含的列族是相同的,也就是说,列族的个数与名称都是相同的,但是每一行中的每个列族中列的个数可以不同
HBase 中的同一个列族里面的数据存储在一起,列族支持动态扩展,可以随时添加新的列,无须提前定义列的数量。
HBase 执行更新操作时,并不会删除数据旧的版本,而是生成一个新的版本,原有的版本仍然保留。
如果查询的时候不提供时间戳,那么系统就会返回离当前时间最近的那一个版本的数据。
HBase 提供了两种数据版本回收方式:一种是保存数据的最后3个版本;另一种是保存最近一段时间内的版本,如最近一个月。

3.HBase数据模型基本概念

HBase 中的数据被存储在表中,具有行和列,是一个多维的映射结构。
1. 表(Table)
HBase采用表来组织数据,表由许多行和列组成,列划分为多个列族。
2. 行(Row)
在表里面,每一行代表着一个数据对象。每一行都是由一个行键(Row Key)和一个或者多个列组成的。行键是行的唯一标识,行键并没有什么特定的数据类型,以二进制的字节来存储,按字母顺序排序。
3. 列族(Column Family)
在定义 HBase 表的时候需要提前设置好列族,表中所有的列都需要组织在列族里面。
4. 列限定符(Column Qualifier)
列族中的数据通过列限定符来进行映射。列限定符不需要事先定义,也不需要在不同行之间保持一致。列限定符没有特定的数据类型,以二进制字节来存储。
5. 列(Column)
列由列族(Column Family)和列限定符(Column Qualifier)联合标识,由“ : ”进行间隔,如 family:qualifiero
6. 单元(Cell)
行键、列族和列限定符一起标识一个单元,存储在单元里的数据称为单元数据,没有特定的数据类型,以二进制字节来存储。
HBase提供基于单元的版本管理功能,版本号默认通过timestamp来标识,并且呈倒序排列;
7. 时间戳(Timestamp)
默认情况下,每一个单元中的数据插入时都会用时间戳来进行版本标识。
读取单元数据时,如果时间戳没有被指定,则默认返回最新的数据;
写入新的单元数据时,如果没有设置时间戳,则默认使用当前时间。
每一个列族的单元数据的版本数量都被 HBase 单独维护,默认情况下,HBase 保留 3 个版本数据。

4.Hbase概念视图(逻辑视图)

在这里插入图片描述

上图是 HBase 的概念视图,是一个存储网页信息的表的片段。行键是一个反向 URL,如 www.cnn.com 反向成 com.cnn.www。
反向 URL 的好处就是,可以让来自同一个网站的数据内容都保存在相邻的位置,从而可以提高用户读取该网站的数据的速度。
contents 列族存储了网页的内容;anchor 列族存储了引用这个网页的链接;mime 列族存储了该网页的媒体类型。

5.Hbase物理视图

在这里插入图片描述
虽然从概念视图层面来看,HBase 的每个表是由许多行组成的,但是在物理存储层面来看,它是采用了基于列的存储方式,而不是像关系型据库那样用基于行的存储方式。这正是 HBase 与关系型数据库的重要区别之一。
在概念视图中,可以看到许多列是空的,也就是说,这些列上面不存在值。
在物理视图中,这些空的列并不会存储成 null,而是根本不会被存储,从而可以节省大量的存储空间。当请求这些空白的单元的时候,会返回 null 值。

6.Hbase主要组件

HBase采用Master/Slave架构搭建集群,它隶属于Hadoop生态系统,由以下类型节点组成:
HMaster节点、HRegionServer节点、ZooKeeper集群,而在底层,它将数据存储于HDFS中,因而涉及到HDFS的NameNode、DataNode等,总体结构如下:
在这里插入图片描述

各组件说明:
1.Client:
	1)使用HBase RPC机制与HMaster和HRegionServer进行通信;
	2)Client与HMaster进行通信进行管理类操作;
	3)Client与HRegionServer进行数据读写类操作;

2.HMaster:类似于NAMENODE RESOURCEMANAGER
HMaster 没有单点问题,HBase中可以启动多个HMaster,通过Zookeeper保证总有一个Master在运行。
HMaster主要负责Table和Region的管理工作:
	1)管理用户对表的增删改查操作;
	2)管理HRegionServer的负载均衡,调整Region分布;
	3)Region Split后,负责新Region的分布;
	4)在HRegionServer停机后,负责失效HRegionServer上Region 的迁移;
	
	

3.HRegionServer:类似于DATANODE NODEMANAGER
HRegionServer一般和DataNode在同一台机器上运行,实现数据的本地性。
HBase中最核心的模块;
	1)维护region,处理对这些region的IO请求;
	2)Regionserver负责切分在运行过程中变得过大的region;
	
	Region的概念:
	Region是HBase数据管理的基本单位。数据的move,数据的balance,数据的split,都是按照region来进行操作的。
	region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。
	一个表中可以包含一个或多个Region。
	每个Region只能被一个RS(RegionServer)提供服务,RS可以同时服务多个Region,来自不同RS上的Region组合成表格的整体逻辑视图。

	HRegionServer详解:
	HRegionServer一般和DataNode在同一台机器上运行,实现数据的本地性。
	1)HRegionServer内部管理了一系列HRegion对象,每个HRegion对应了Table中的一个Region。
	2)一个Table可以有多个Region,他们可以在一个相同的HRegionServer上,也可以分布在不同的HRegionServer上,一个HRegionServer可以有多个HRegion,他们分别属于不同的Table3)HRegion由多个Store(HStore)构成,每个HStore对应了一个Table在这个HRegion中的一个Column Family,即每个Column Family就是一个集中的存储单元,因而最好将具有相近IO特性的Column存储在一个Column Family,以实现高效读取。
	4)每个HRegionServer中都会有一个HLog对象。HLog对象:数据库的日志。
	每个HRegionServer中都会有一个HLog对象。用户进行数据写入的时候,会先把所有数据到HLog文件,同时在HDFS进行备份,然后再写入MemStore中,写到一定程度由MemStore根据一定的算法将数据Flush到底层HDFS文件中(HFile)。
	引入HLog原因:灾难恢复。在分布式系统环境中,无法避免系统出错或者宕机,一旦HRegionServer意外退出,MemStore中的内存数据就会丢失,引入HLog就是防止这种情况。
	5)一个HStore由一个MemStore 和0个或多个StoreFile组成。
		MemStore:
		是一个写缓存(In Memory Sorted Buffer),的写在完成WAL日志写后,会 写入MemStore中,由MemStore根据一定的算法将数据Flush到底层HDFS文件中(HFile),通常每个HRegion中的每个 Column Family有一个自己的MemStore。
		StoreFile(Hfile):
		用于存储HBase的数据(Cell/KeyValue)。在HFile中的数据是按RowKey、Column Family、Column排序,对相同的Cell(即这三个值都一样),则按timestamp倒序排列。

4.Zookeeper:
1)ZooKeeper为HBase集群提供协调服务,它管理着HMaster和HRegionServer的状态(available/alive等),并且保证集群中只有一个HMaster,会在它们宕机时通知给HMaster,从而HMaster可以实现HMaster之间的故障转移;
2)实时监控HRegionServer的上线和下线信息,并实时通知给HMaster;
3)存储HBase的Meta Table(hbase:meta)的位置,Meta Table表存储了集群中所有用户HRegion的位置信息,且不能split;
4)Zookeeper的引入使得Master不再是单点故障 HMaster虽然可以开启多个 但是不是越多越好 两个 --> 只开一个 nn2 贡献出来保存region nn2 没有 block --> 尴尬

7.Hbase安装

1.Hbase启动
#第一步:先启动集群zookeeper
[hadoop@nn1 conf]$ sh ~/zk_base_op/zk_ssh_all.sh /usr/local/zookeeper/bin/zkServer.sh status
[hadoop@nn1 conf]$ sh ~/zk_base_op/zk_ssh_all.sh /usr/local/zookeeper/bin/zkServer.sh start
#第二步:启动集群hdfs
start-dfs.sh
#第三步:启动集群hbase
start-hbase.sh
#启动后查看进程
[hadoop@nn1 conf]$ sh ~/hadoop_base_op/ssh_all.sh jps

#开启hbase shell
hbase shell
#查看hbase状态
status
#查看hbase版本
version

2.Hbase关闭
#关闭集群hbase
stop-hbase.sh

3.开启、关闭hbase单独
hbase-daemon.sh start/stop regionserver
hbase-daemon.sh start/stop master

4.查看hbase的web界面
http://nn1.hadoop:60010

5.查看Hbase日志
[hadoop@nn1 conf]$ cd /usr/local/hbase/logs/
[hadoop@nn1 logs]$ ll
[hadoop@nn1 logs]$ tail -300 hbase-hadoop-master-nn1.hadoop.log

6.1在zookeeper中查看hbase meta 表所在的服务器
[hadoop@nn1 ~]$ zkCli.sh -server nn1.hadoop
[zk: nn1.hadoop(CONNECTED) 0] ls /
[zk: nn1.hadoop(CONNECTED) 1] ls /hbase
[zk: nn1.hadoop(CONNECTED) 2] get /hbase/meta-region-server
6.2在zookeeper中查看hbase的 hmaster的所在主机
[zk: nn1.hadoop(CONNECTED) 3] get /hbase/master

8.Hbase的数据读写流程

1.首先客户端寻找HRegionServer,及缓存位置信息
在这里插入图片描述

1.第一步:先从缓存中或zookeeper中获取hbase:meta表的位置(元数据信息位置)
2.第二步:再从缓存中或hbase:meta表中查询用户table对应请求的RowKey所在的HRegionServerde的位置

2.写数据流程
在这里插入图片描述

1)通过2.8.1找到该写数据最终需要去的HRegionServer;
2)然后客户端将写请求发送给相应的HRegionServer,在HRegionServer中它首先会将该写操作写入WAL(Hlog)日志文件中(Flush到磁盘中)3)写完WAL日志文件后,HRegionServer根据Put中的TableName和RowKey,startkey、endkey找到对应的HRegion,并根据Column Family找到对应的HStore,并将Put写入到该HStore的MemStore中。
4)此时写成功,并返回通知客户端。
5)写入MemStore后的操作:
	1.触发MemStore Flush操作:数据写入MemStore后,一直到MemStore满 → Flush成一个StoreFile,直至增长到一定阈值
	2.触发StoreFiles Compact操作:达到一定阈值后,将多个StoreFile小文件合并成一个大StoreFile大文件,逐步形成越来越大的StoreFile,同时进行版本合并和数据删除
	3.触发Region split操作:当单个StoreFile大文件超过一定阈值(Region split 阈值)后,触发Split操作,把当前Region Split成2个Region,Region会下线, 新Split出的2个子Region会被HMaster分配到相应的HRegionServer上,使得原先1个Region的压力得以分流到2个Region上;

说明:Region拆分策略:
1.Region大小考量的因素
	1)Region大,数目太少就会妨碍可扩展性,降低并行能力,导致压力不够分散;
	2)region小,数目太多就会造成性能下降;

2.HRegionServer拆分region的步骤:是先将该region下线,然后拆分,将其子region加入到hbase:meta表中,再将他们加入到原本的HRegionServer中,最后汇报Master。

3.hbase在写入数据 为了防止regionserver热点问题,我们需要进行Region的拆分(分为split前、split中、split后)
可以通过设置RegionSplitPolicy的实现类来指定拆分策略,RegionSplitPolicy类的实现类有:
	ConstantSizeRegionSplitPolicy
	IncreasingToUpperBoundRegionSplitPolicy
	DelimitedKeyPrefixRegionSplitPolicy
	KeyPrefixRegionSplitPolicy

	其中:
	1.ConstantSizeRegionSplitPolicy
	仅当region大小超过常量值(hbase.hregion.max.filesize大小,默认为10G)时,才进行拆分。
	2. IncreasingToUpperBoundRegionSplitPolicy
	默认region split策略。即当同一table在同一regionserver上的region数量在[0,100)之间时按照如下的计算公式算,否则按照上一策略计算:
	Min (R^3* "hbase.hregion.memstore.flush.size"*2, "hbase.hregion.max.filesize")
        R为同一个table中在同一个regionserver中region的个数,
        hbase.hregion.memstore.flush.size默认为128M,
        hbase.hregion.max.filesize默认为10G。
	3. DelimitedKeyPrefixRegionSplitPolicy
	保证以分隔符前面的前缀为splitPoint,保证相同RowKey前缀的数据在一个Region中。如果定义rowkey时,采用'_'作为字段分隔符(如:userid_eventid),则采用该策略拆分之后,能够确保具有相同userid的记录隶属于同一Region。
	4. KeyPrefixRegionSplitPolicy                    
	保证具有相同前缀的row在一个region中(要求设计中前缀具有同样长度)。指定rowkey前缀位数划分region,通过读取table的prefix_split_key_policy.prefix_length属性,该属性为数字类型,表示前缀长度,在进行split时,按此长度对splitPoint进行截取。

3.读数据流程
在这里插入图片描述

1)通过2.8.1找到要读的数据的HRegionServer。
2)根据读取的TableName和RowKey的startkey 、 endkey 找到对应的HRegion。
3)每个regionserver只有一个blockcache(读缓存),读取数据时,先到memestore上读数据,找不到再到blockcahce上找数据,再查不到则到磁盘(storefile)查找,并把读入的数据同时放入blockcache。

9.Hbase的数据结构

1.传统数据库存数据储结构:采用B+树的方式
B+树最大的性能问题是会产生大量的随机IO,随着新数据的插入,叶子节点会慢慢分裂,逻辑上连续的叶子节点在物理上往往不连续,甚至分离的很远,但做范围查询时,会产生大量读随机IO;

2.Hbase数据存储结构:为了克服B+树的弱点,引入了LSM树的概念,即Log-Structured Merge-Trees;
LSM树本质上就是在读写之间取得平衡,和B+树相比,它牺牲了部分读性能,用来大幅提高写性能。
LSM树原理把一棵大树拆分成N棵小树,它首先写入内存中,随着小树越来越大,内存中的小树会flush到磁盘中,磁盘中的树定期可以做merge操作,合并成一棵大树,以优化读性能。

3.B+树与LSM-Tree树本质区别
他们本质不同点在于他们使用现代硬盘的方式,尤其是磁盘。从磁盘使用方面讲,RDBMS是寻道型,它需要随机读写数据。LSM-Tree则属于传输型,它会顺序读写数据。

10.Hbase的rowkey设计

Row Key特点:
	1.Row Key可以是任意字符串,最大长度64KB,实际应用中一般为10~100bytes;1 1000000001 1000000002  19 1a 1z 20 2z
	2.RowKey是按照字典序存储,因此,设计row key时,要充分利用这个排序特点,将经常一起读取的数据存储到一块,将最近可能会被访问的数据放在一块;
	3.region的拆分策略和Row Key主键设计有很大关系,Hregionserver的热点问题就是MapReduce和hive的数据倾斜问题,所以hbase也要求数据平衡。

Row Key支持三种检索方式
1)通过单个row key访问:即按照某个row key键值进行get操作;
2)通过row key的范围进行scan:即通过设置startRowKey和endRowKey,在这个范围内进行扫描
3)全表扫描:即直接扫描整张表中所有行记录,只适合小数据量情况。
Hbase中没有join的概念,大表的结构可以使得不需要join。

RowKey设计原则:
1)要保证rowkey的唯一性。
2)wkey 长度建议是越短越好,不要超过16个字节。
3)Rowkey的散列原则
如果Rowkey是按时间戳的方式递增,不要将时间放在二进制码的前面,建议将Rowkey的高位作为散列字段,由程序循环生成,低位放时间字段,这样将提高数据均衡分布在每个Regionserver实现负载均衡的几率。

在这里插入图片描述

三、Hbase Shell:DDL语句操作

Meta:hbase:meta(全限定名称;存储元数据信息表)
Hbase shell操作是hbase通过jruby把所有的命令转成java方法执行

一般操作:
查询服务器状态:status
查询版本:version

Hbase的命名空间-->MySQL数据库
Hbase的表-->MySQL的数据库别名
Hbase的列簇-->MySQL的表
Hbase的列限定符-->MySQL的字段
Hbase的但愿-->MySQL的字段值

DDL语句操作:
1.命名空间操作
# 创建命名空间
create_namespace 'myns1'
# 显示命名空间
list_namespace
#查看命名空间下有什么表
list_namespace_tables 'myns1'
# 删除命名空间, 在删除一个命名空间时,该命名空间不能包含任何的表,否则会报错
drop_namespace '命名空间名'

2.创建表
# 创建默认命名空间的表
create '表名称','列族名称1','列族名称2','列族名称N'
# 创建带有命名空间的表
create '命名空间:表名称','列族名称1','列族名称2','列族名称N'
# 创建带有命名空间的表示例
create 'myns1:table1','cf1','cf2','cf3'

3.列出某个命名空间下的所有表
# 列出某个命名空间下的所有表
list 'myns1.*'

4.获得表的描述
# 获得表的描述(查看表结构)
desc '命名空间:表名'

5.删除一个列族
# 删除一个列族(myns1:table1 表的 cf2 列族)
alter 'myns1:table1',{NAME=>'cf2',METHOD=>'delete'}
# 删除多个列族 列族属性操作的时候 属性名 是区分大小写 也就是说 NAME --> 方法 METHOD --> 方法 delete 参数
alter 'myns1:table2', { NAME => 'cf3', METHOD => 'delete'},{ NAME => 'cf2', METHOD => 'delete'}

6.将表下线/下线(注意 : 下线后,该表不能进行查询)
检测表是否下线:is_disabled "myns1:tb1"
将表下线:disable "myns1:tb1"
检测表是否上线:is_enabled "myns1:tb1"
将表上线: enable "myns1:tb1"

7.删除一个表
# 删除一个表(在线表,会报错)
drop 'myns1:table1'
# 删除一个表(将表下线,再删除)
将表下线:disable "myns1:tb1"
再删除表:drop "myns1:tb2"

8.判断表是否存在
# 判断表是否存在
exists "tb1"  //公司常用
exists "myns1:tb1"

四、Hbase Shell:DML语句操作

DML语句操作:
1. 添加数据
	# 语法:put <table>,<rowkey>,<family:column>,<value>,<timestamp>
	# 如果不写timestamp,则系统默认
# 插入数据前要保证表是enable状态
# 重新创建表
create 'myns1:table2', 'cf1', 'cf2'
#基本信息的列族
put 'myns1:table2','hb_1', 'cf1:name','zhaowenming'
put 'myns1:table2','hb_1', 'cf1:age','25'
put 'myns1:table2','hb_1', 'cf1:sex','M'
#证件信息的列族
put 'myns1:table2','hb_1', 'cf2:cert_type','身份证'
put 'myns1:table2','hb_1', 'cf2:cert_no','130102199405286392'

2. 获取数据
get: 获取表中一行数据,不能扫描全表
# 语法:get <table>,<rowkey>,[<family:column>,....]
#获取一行数据
get 'myns1:table2','hb_1'
#获取一行,一个列族的所有数据
get 'myns1:table2','hb_1','cf1'
#获取一行,一个列族中一个列的数据
get 'myns1:table2','hb_1','cf1:name'

#获取一行的列族
get 'myns1:table2', 'hb_1', {COLUMN => 'cf1'}
#获取一行的某列族的列
get 'myns1:table2', 'hb_1', {COLUMN => 'cf1:name'}
#获取一行某列族的列并匹配时间戳
get 'myns1:table2', 'hb_1', {COLUMN => 'cf1:name', TIMESTAMP => 1562742642169} 
#获取一行中,FILTER筛选器,binary二进制数组的值为110125的列
get 'myns1:table2', 'hb_1', {FILTER => "ValueFilter(=, 'binary:130102199405286392')"}

3. 更新数据
#语法:重新put,put时会覆盖原来的数据
-- 修改年龄
put 'myns1:table2','hb_1','cf1:age','25'
-- 查看年龄
get 'myns1:table2','hb_1','cf1:age'

4. 通过timestamp来获取两个版本的数据
get 'myns1:table2','hb_1',{COLUMN=>'cf1:age',TIMESTAMP=>1562746800144}
get 'myns1:table2','hb_1',{COLUMN=>'cf1:age',TIMESTAMP=>1562746813618}

5. scan扫描
# 语法:scan <table> ,{COLUMNS => [ <family:column>,.... ], LIMIT => num}
# 添加数据
put 'myns1:table2','hb_2', 'cf2:cert_type','身份证'
put 'myns1:table2','hb_2', 'cf2:cert_no','130102199805236580'
put 'myns1:table2','hb_3', 'cf2:cert_type','身份证'
put 'myns1:table2','hb_3', 'cf2:cert_no','130102199706237795'
put 'myns1:table2','hb_4', 'cf2:cert_type','身份证'
put 'myns1:table2','hb_4', 'cf2:cert_no','130102199705142396'
#扫描全表,大表操作不可取
scan 'myns1:table2'
#获取表中前两行
scan 'myns1:table2', {LIMIT => 2}
#扫描表中指定列族数据
scan 'myns1:table2', {COLUMNS => 'cf1'}
#扫描表中执行列族中列的数据
scan 'myns1:table2', {COLUMNS => 'cf2:cert_no'}
#扫描表中值=130102199705142396 的数据
scan 'myns1:table2', FILTER=>"ValueFilter(=,'binary:130102199705142396')"
#扫描表的范围 包含 STARTROW 的范围 但是不包含 STOPROW 的范围
scan 'myns1:table2' , {STARTROW => 'hb_2', STOPROW => 'hb_3'}

6. 删除行中某列数据
# 语法:delete <table>, <rowkey>, <family:column>
# 修改数据
put 'myns1:table2', 'hb_4','cf2:cert_type', 'shenfenzheng'
get 'myns1:table2', 'hb_4','cf2:cert_type'
put 'myns1:table2', 'hb_4','cf2:cert_type', 'idcard'
get 'myns1:table2', 'hb_4','cf2:cert_type'
# 删除行中某列数据(指定列名,会删除执行列的所有版本数据)
delete 'myns1:table2', 'hb_4', 'cf2:cert_type'
get 'myns1:table2', 'hb_4','cf2:cert_type'(获取数据 所有版本都删除)
get 'myns1:table2','hb_4',{TIMESTAMP=>1733829623580}(验证一下 数据已删除)
get 'myns1:table2','hb_4',{TIMESTAMP=>1733