评论

收藏

[NoSQL] Hbase的三种索引_全局索引,覆盖索引,本地索引(七)

数据库 数据库 发布于:2021-06-30 20:39 | 阅读数:456 | 评论:0

  
  文章目录


  • 分布式NoSQL列存储数据库Hbase(七)


    • 知识点02:课程目标
    • 知识点03:Phoenix二级索引设计
    • 知识点04:二级索引:全局索引设计
    • 知识点05:二级索引:全局索引实现
    • 知识点06:二级索引:覆盖索引设计
    • 知识点07:二级索引:覆盖索引实现
    • 知识点08:二级索引:本地索引设计
    • 知识点09:二级索引:本地索引实现
    • 知识点10:二级索引:函数索引【了解】
    • 知识点11:集群角色功能:Master
    • 知识点12:集群角色功能:RegionServer
    • 知识点13:集群角色功能:HDFS与ZK
    • 知识点14:Hbase读写流程:写入流程
    • 知识点15:Hbase读写流程:meta表
    • 知识点14:Hbase读写流程:写入流程
    • 知识点15:Hbase读写流程:meta表


  分布式NoSQL列存储数据库Hbase(七)

  •   如何培养解决错误的能力

    •   Hbase启动以后,进程会自动消失?
    •   运行程序时的一些报错?
    •   所有错误都是有日志的

      •   软件的错误:找到软件的日志
          [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2aGqsq2h-1616590200777)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324092337557.png)]
        tail -100f logs/hbase-root-master-node1.log

    •   Java的程序错误:都是Exception

      • 根据Exception的错误,分析原因
      • ArrayOutOfIndexException:数据越界异常

        • 引用了一个不存在的下标
        • 排查:引用元素的位置

      • ConnectionException:Connection Refused:连接拒绝异常

        • 请求地址:hostname:port

          • 主机名不正确
          • 端口不对

        • 进程没有正常启动,端口没有开放

      • NullException:空指针异常

        • 变量的值为null

      • OutOfMemoryException:内存溢出异常

        • 内存空间存储不足

      • ClassNotFoundException:类找不到

        • 缺少jar包,jar包有问题
        • jar包冲突

      • CastClassException:转换异常

    •   建议

      • 第一:先百度,查询Exception
      • 第二:如果第一步解决不了,超过5分钟咨询老师
      • 第三:总结错误

        • 现象
        • 分析
        • 解决




知识点02:课程目标

  • Phoenix实现二级索引

    • 为什么要构建二级索引?
    • 如何构建二级索引?【重点】

      • 全局索引
      • 覆盖索引
      • 本地索引
      • 三种索引区别和各自的应用场景


  • Hbase整体读写流程

    • 集群中每个角色的具体功能

      • Master
      • RegionServer

    • Hbase读写数据中:元数据的内容和检索过程==【重点】==


知识点03:Phoenix二级索引设计


  •   目标

    • 基于Phoenix构建Hbase二级索引并维护二级索引

  •   分析

    • 为什么需要构建二级索引?

      • 因为Hbase使用Rowkey作为唯一索引,无法满足大部分的查询走索引,导致性能较差
      • 构建二级索引:通过走两次索引代替全表扫描

    • Phoenix如何实现二级索引?

      • Phoenix底层构建了大量的协处理器,来实现二级索引的构建


  •   实现

    •   step1:根据数据存储需求,创建原始数据表,将数据写入原始数据表
      rowkey:idnameage
    •   step2:根据数据查询需求,构建二级索引,Phoenix自动创建索引表
      create index indexName on tbName(colName);
      rowkey:name_id
    •   step3:查询数据时,Phoenix根据过滤条件是否存在二级索引,优先判断走二级索引代替全表扫描
    •   step4:原始数据表发生数据变化时,Phoenix会自动更新索引表的数据

  •   总结

    • 在Phoenix中二级索引实现完全由Phoenix自主实现
    • 不需要关心底层的实现,只需要使用语法创建索引即可
    • http://phoenix.apache.org/secondary_indexing.html


知识点04:二级索引:全局索引设计


  •   目标

    • 了解二级索引中全局索引的设计思想

  •   分析

    • 什么是全局索引?

      • 当为某一列创建全局索引时,Phoenix自动创建一张索引表,将创建索引的这一列加上原表的rowkey作为新的rowkey


  •   实现

    •   原始数据表
      rowkey:idnameage
    •   需求:根据name进行数据查询
    •   创建全局索引
      create index index01 on tbname(name);
    •   自动构建索引表
      rowkey:name_idcol:占位值
    •   查询

      • 先查询索引表:通过rowkey获取名称对应的id
      • 再查询数据表:通过id查询对应的数据


  •   总结

    •   **特点:**默认只能对构建索引的字段做索引查询,如果查询中包含了不是索引的字段或者条件不是索引字段,不走索引
    •   走索引
      select name from table
      select name from table where name = value

      •   不走索引
        select * from table where name = value

    •   **应用:**写少读多

      • 当原表的数据发生更新操作提交时,会被拦截
      • 先更新所有索引表,然后再更新原表



知识点05:二级索引:全局索引实现


  •   目标

    • 基于Phoenix实现全局索引的测试

  •   分析

    • step1:先创建原始数据表
    • step2:基于查询条件创建索引
    • step3:实现索引查询

  •   实现

    •   不构建索引,先查询,查看执行计划
      select "user_id" from ORDER_DTL where "user_id" = '8237476';
      explain select "user_id" from ORDER_DTL where "user_id" = '8237476';
        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DCGxHMk7-1616590200779)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324102219687.png)]
    •   基于user_id构建全局索引
      create index GBL_IDX_ORDER_DTL on ORDER_DTL(C1."user_id");
    •   查看索引表
      !tables
        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dmsKS7ME-1616590200780)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324102348151.png)]
        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HLoZolzn-1616590200781)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324102530846.png)]
        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TQk7O8T7-1616590200782)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324102548631.png)]
    •   查询数据及查询计划
      select "user_id" from ORDER_DTL where "user_id" = '8237476';
      explain select "user_id" from ORDER_DTL where "user_id" = '8237476';
        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rr9tNjVj-1616590200783)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324102631657.png)]
    •   如果查询条件不是索引字段
      explain select "user_id" from ORDER_DTL where "money" = 9390.0;
    •   如果查询内容不是索引字段,查看执行计划
      explain select "user_id", "id", "money" from ORDER_DTL where "user_id" = '8237476';
    •   强制走索引
      explain select /*+ INDEX(ORDER_DTL GBL_IDX_ORDER_DTL) */ * from ORDER_DTL where "user_id" = '8237476';
    •   删除索引
      drop index GBL_IDX_ORDER_DTL on ORDER_DTL;

  •   总结

    • 全局索引是最常用的基础二级索引类型
    • 索引表结构

      • rowkey:查询条件字段 + 原表rowkey

    • 应用:适合于读多写少的场景
    • 特点:如果查询条件或者查询内容中包含非索引字段,将不走索引,可以强制走索引


知识点06:二级索引:覆盖索引设计


  •   目标

    • 了解二级索引中覆盖索引的设计思想

  •   分析

    • 什么是覆盖索引?

      • 在构建全局索引时,将经常作为查询条件的列放入索引表中,直接通过索引表来返回数据结果


  •   实现

    •   原始数据表
      rowkey:idnameage  addr  phone
    •   需求:根据name进行数据查询
    •   创建全局索引
      create index index01 on tbname(name);
    •   自动构建索引表
      rowkey:name_idcol:占位值
    •   如果需求发生改变,查询name和age,上面的全局索引会失效
    •   创建全局+覆盖:include(age)
      create index index01 on tbname(name) include(age);
    •   自动构建索引表
      rowkey:name_idcol:age
      select name from table;
      select name from table where age = 20
      select name , age from table

  •   总结

    • **特点:**基于全局索引构建,将常用的查询结果放入索引表中,直接从索引表返回结果
    • **应用:**适合于查询条件比较固定,数据量比较小的场景下
    • 注意:不建议将大部分列都放入覆盖索引,导致索引表过大,性能降低


知识点07:二级索引:覆盖索引实现


  •   目标

    • 基于Phoenix实现覆盖索引的测试

  •   分析

    • step1:先创建原始数据表
    • step2:基于查询条件创建覆盖索引
    • step3:实现索引查询

  •   实现

    •   不构建索引,先查询,查看执行计划
      select "user_id", "id", "money" from ORDER_DTL where "user_id" = '8237476';
      explain select "user_id", "id", "money" from ORDER_DTL where "user_id" = '8237476';
    •   基于user_id构建全局索引,运行通过user_id查询订单id和支付金额
      create index GBL_IDX_ORDER_DTL on ORDER_DTL(C1."user_id") INCLUDE("id", C1."money");
    •   查看索引表
      !tables
        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WeyeOlZG-1616590200784)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324104259966.png)]
        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qJodnjuq-1616590200784)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324104408082.png)]
    •   查询数据
      select "user_id", "id", "money" from ORDER_DTL where "user_id" = '8237476';
    •   查看执行计划
      explain select "user_id", "id", "money" from ORDER_DTL where "user_id" = '8237476';
        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oWBK8XF7-1616590200785)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324104452747.png)]
    •   如果查询条件不是索引字段
      [/list]  explain select “user_id”, “id”, “money” from ORDER_DTL where “pay_way” = 1;
      
      - 如果查询内容不是索引字段,查看执行计划
      ```sql
      explain select "user_id", "id", "pay_way" from ORDER_DTL where "user_id" = '8237476';
        

      •   使用HINT强制走索引
        explain select /*+ INDEX(ORDER_DTL GBL_IDX_ORDER_DTL) */ * from ORDER_DTL where "user_id" = '8237476';
      •   删除索引
        drop index GBL_IDX_ORDER_DTL on ORDER_DTL;

    •   总结

      •   覆盖索引是基于全局索引实现的
      •   目的是将常用的查询结果放入索引表中,直接从索引表返回数据


    知识点08:二级索引:本地索引设计


    •   目标

      • 了解二级索引中本地索引的设计思想

    •   分析

      • 什么是本地索引?

        • 将索引数据与对应的原始数据放在同一台机器,避免了跨网络传输,提高了写的性能


    •   实现

      • 构建索引数据时,将索引数据直接存储在原表中,用一个列族来实现

    •   总结

      • 特点

        • 即使查询数据中包含了非索引字段,也会走本地索引
        • 本地索引会修改原始数据

          • 如果构建了本地索引,不能通过Hbase的API来读写数据的,必须通过Phoenix来实现读写

        • 本地索引对盐表不生效的

      • 应用:写多读少

        • 提高构建索引时对写的性能的影响
        • 最终所有索引都是为了提高读的性能的



    知识点09:二级索引:本地索引实现

    知识点10:二级索引:函数索引【了解】


    •   目标

      • 了解Hbase中的函数索引的概念

    •   分析

      • 本地、覆盖、全局:都是基于查询的列构建索引
      • 什么是函数索引?

        • 可以基于一个函数表达式去构建索引


    •   实现

      •   查询:过滤的条件是一个函数
        SELECT EMP_ID FROM EMP WHERE UPPER(FIRST_NAME||' '||LAST_NAME)='JOHN DOE'
      •   构建索引
        CREATE INDEX UPPER_NAME_IDX ON EMP (UPPER(FIRST_NAME||' '||LAST_NAME))
      •   Hive中

        •   SQL:语法
        •   函数

          •   字符串

            • substr

          •   replace_regex

            •   concat/concat_ws

              • concat:直接拼接每个字符串,只有有1列为null,整个结果为null
              concat(str1,str2,str3……)
                       

              •   concat_ws:可以指定分隔符,只要有1列不为null,整个结果不为null
                concat(分隔符,str1,str2,str3……)

            •   instr
            •   ……

          •   日期

            • 转换类:from_unix,unix_timestamp
            • 获取:year、ceil、quator、month、day、hour

          •   条件

            • if
            • case when

          •   JSON处理:json_tuple,get_json_object
          •   窗口函数:重点:row_number,rank,dense_rank,lead,lag,sum
          •   URL解析:parse_url_tuple



    •   总结

      • 函数索引就是基于函数表达式创建索引,当执行相同的函数表达式查询时,可以通过索引实现快速查询
      • 一般不用


    知识点11:集群角色功能:Master
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5qsDzwNT-1616590200786)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210323223056968.png)]

    •   管理所有从节点:RegionServer

      •   监听Regionserver的状态,如果RegionServer发生故障,会实现这台RegionServer的数据恢复
      •   基本原理:所有RegionServer会在ZK中注册一个临时节点,Master会监听Zookeeper中的这些节点

        • 类似于HA选举的原理

      •   数据是如何恢复的?

        •   数据存储的位置
        •   内存:RegionServer的内存中

          •   如果RegionServer断电故障,内存中的数据丢失
          •   解决:通过持久化日志来实现

            •   WAL:HLog,write ahead log:预写日志

              • 数据在写入内存之前,会将这个操作记录在WAL中
              • 如果内存数据丢失,可以通过WAL进行恢复
              • 存储在HDFS上
                [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JK77zwSO-1616590200786)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324113740340.png)]
                [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GGdmPWuF-1616590200786)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324113753586.png)]



        •   磁盘:HDFS中

          • 如果RegionServer故障,不影响HDFS的数据



    •   管理元数据

      • Master会接受所有DDL请求
      • Master启动时会加载meta表和namespace的数据,获取元数据记录在ZK中
      • Master会将所有管理类的元数据存储在ZK中
        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lohj84Ke-1616590200787)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210324114021119.png)]

    •   管理Region的分配

      • 创建表、分配region
      • regionserver故障,重新分配region到别的regionserver上
      • region分裂,将新的region分配到regionserver上


    知识点12:集群角色功能:RegionServer
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9prEEpeU-1616590200787)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210323223219354.png)]

    • 负责管理所有Region的数据读写,接受客户端对于region的读写请求
    • 维护所有存储角色

      •   WAL:write ahead log:预写日志
      •   Region:存储分区
      •   Store:列族,存储单元
      •   Memstore:写缓存,数据先写入MemStore
      •   BlockCache:读缓存,如果第一次从HDFS中读取,可以配置将读取的结果放入读缓存,下次直接从读缓存中读取

        •   读的顺序

          •   先读memstore
          •   如果没有,数据在HDFS的文件中:怎么能让Hbase读HDFS文件能很快?

            • Rowkey是有序的
            • 列族的设计
            • 二进制文件

          •   可以指定对列族的数据是否开启读缓存,如果开启了读缓存

            •   第一次从HDFS读取完成以后,将结果放入读缓存BlockCache:内存区域
            •   第二次开始

              •   先读memstore
              •   再读Blockcache
              •   再读HDFS




      •   StoreFile:如果MemStore存储的容量达到一定条件,将MEMStore中的数据写入HDFS

    • 实现分布式内存存储

    知识点13:集群角色功能:HDFS与ZK


    •   HDFS功能

      • 用于实现HBASE大量数据的持久化存储
      • 当MemStore中的数据过多,就会进行Flush【Spill】:将数据从内存溢写到HDFS上

    •   ZooKeeper功能

      • 用于实现HMaster的HA,辅助选举
      • 用于存储核心元数据:管理元数据

        • 供Master实现管理操作

          • Hbase中有哪些ns、哪些表、哪些rs、master是谁,正在执行的操作


      • 表的元数据不在Zookeeper中

        • 表的元数据在meta表中
        • 表的元数据:表有几个region,每个region的范围、region所在的地址



    知识点14:Hbase读写流程:写入流程
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iB5AlLvh-1616590200788)(20210324_分布式NoSQL列存储数据库Hbase(七).assets/image-20210323223403690.png)]

    •   目标

      •   掌握Hbase数据写入的流程
      •   当执行一条Put操作,数据是如何写入Hbase的?
        put 表名rowkey列族:列值

    •   分析

      •   step1:根据表名获取这张表对应的所有Region的信息
      •   step2:根据Rowkey判断具体写入哪个Region
      •   step3:将put操作提交给这个Region所在的RegionServer
      •   step4:RegionServer将数据写入Region,根据列族判断写入哪个Store

    •   总结

    知识点15:Hbase读写流程:meta表


    •   目标

      • 了解hbase:meta表的存储内容及功能
      • 问题1:如何知道这张表对应的region有哪些?
      • 问题2:如何知道每个Region的范围的?
      • 问题3:如何知道Region所在的RegionServer地址的?

    •   分析

      • 肯定有个地方存储了表与Region的关系以及Region的信息

    •   实现

      • hbase:meta表

    •   总结
      中的数据过多,就会进行Flush【Spill】:将数据从内存溢写到HDFS上

    •   ZooKeeper功能

      • 用于实现HMaster的HA,辅助选举
      • 用于存储核心元数据:管理元数据

        • 供Master实现管理操作

          • Hbase中有哪些ns、哪些表、哪些rs、master是谁,正在执行的操作


      • 表的元数据不在Zookeeper中

        • 表的元数据在meta表中
        • 表的元数据:表有几个region,每个region的范围、region所在的地址



    知识点14:Hbase读写流程:写入流程
      [外链图片转存中…(img-iB5AlLvh-1616590200788)]

    •   目标

      •   掌握Hbase数据写入的流程
      •   当执行一条Put操作,数据是如何写入Hbase的?
        put 表名rowkey列族:列值

    •   分析

      •   step1:根据表名获取这张表对应的所有Region的信息
      •   step2:根据Rowkey判断具体写入哪个Region
      •   step3:将put操作提交给这个Region所在的RegionServer
      •   step4:RegionServer将数据写入Region,根据列族判断写入哪个Store

    •   总结

    知识点15:Hbase读写流程:meta表


    •   目标

      • 了解hbase:meta表的存储内容及功能
      • 问题1:如何知道这张表对应的region有哪些?
      • 问题2:如何知道每个Region的范围的?
      • 问题3:如何知道Region所在的RegionServer地址的?

    •   分析

      • 肯定有个地方存储了表与Region的关系以及Region的信息

    •   实现

      • hbase:meta表

    •   总结


      
关注下面的标签,发现更多相似文章