zoukankan      html  css  js  c++  java
  • 转:Hive性能优化之ORC索引–Row Group Index vs Bloom Filter Index

    之前的文章《更高的压缩比,更好的性能–使用ORC文件格式优化Hive》中介绍了Hive的ORC文件格式,它不但有着很高的压缩比,节省存储和计算资源之外,还通过一个内置的轻量级索引,提升查询的性能。这个内置的轻量级索引,就是下面所说的Row Group Index。

    其实ORC支持的索引不止这一种,还有一种BloomFilter索引,两者结合起来,更加提升了Hive中基于ORC的查询性能。

    说明一下:本文使用Hive2.0.0 + hadoop-2.3.0-cdh5.0.0作为测试环境。表lxw1234_text为text格式保存,总记录数为12000920。

    Row Group Index

    由之前的文章知道,一个ORC文件包含一个或多个stripes(groups of row data),每个stripe中包含了每个columnmin/max值的索引数据,当查询中有<,>,=的操作时,会根据min/max值,跳过扫描不包含的stripes

    而其中为每个stripe建立的包含min/max值的索引,就称为Row Group Index,也叫min-max Index,或者Storage Index。在建立ORC格式表时,指定表参数’orc.create.index’=’true’之后,便会建立Row Group Index,需要注意的是,为了使Row Group Index有效利用,向表中加载数据时,必须对需要使用索引的字段进行排序,否则,min/max会失去意义。另外,这种索引通常用于数值型字段的查询过滤优化上。

    看下面的例子:

    1. CREATE TABLE lxw1234_orc2 stored AS ORC
    2. TBLPROPERTIES
    3. ('orc.compress'='SNAPPY',
    4. 'orc.create.index'='true',
    5. 'orc.bloom.filter.fpp'='0.05',
    6. 'orc.stripe.size'='10485760',
    7. 'orc.row.index.stride'='10000')
    8. AS
    9. SELECT CAST(siteid AS INT) AS id,
    10. pcid
    11. FROM lxw1234_text
    12. DISTRIBUTE BY id sort BY id;

    直接执行下面的查询(未使用索引):

    1. SELECT COUNT(1) FROM lxw1234_orc1 WHERE id >= 1382 AND id <= 1399;

    orc index

    很明显,扫描了所有记录。再使用索引查询:

    1. set hive.optimize.index.filter=true;
    2. SELECT COUNT(1) FROM lxw1234_orc1 WHERE id >= 1382 AND id <= 1399;

    orc index

    可以看到,只扫描了部分记录,即根据Row Group Index中的min/max跳过了WHERE条件中不包含的stripes,索引有效果。

    假如有下面的查询:

    1. SET hive.optimize.index.filter=true;
    2. SELECT COUNT(1) FROM lxw1234_orc1 WHERE id >= 0 AND id <= 1000
    3. AND pcid IN ('0005E26F0DCCDB56F9041C','A');

    执行的过程大概是这样的:

    先根据Row Group Index中的min/max,判断哪些stripes/file包含在内,接着逐行扫描,过滤pcid IN (‘0005E26F0DCCDB56F9041C’,’A’)的记录。

    orc index

    可以看到,没有全表扫描,跳过了一部分stripes。这样看来,如果where后面的id范围很大,完全可能会包含所有的文件,再根据pcid过滤时候,又相当于全表扫描了。

    对于这种查询场景的优化策略,就是下面的BloomFilter索引。

    Bloom Filter Index

    之前有篇文章《大数据去重统计之BloomFilter》,介绍过BloomFilter的原理和Java版的例子。Hive的ORC中基于此,提供了BloomFilter索引,用于性能优化。

    在建表时候,通过表参数”orc.bloom.filter.columns”=”pcid”来指定为那些字段建立BloomFilter索引,这样,在生成数据的时候,会在每个stripe中,为该字段建立BloomFilter的数据结构,当查询条件中包含对该字段的=号过滤时候,先从BloomFilter中获取以下是否包含该值,如果不包含,则跳过该stripe.

    看下面的建表语句,为pcid字段建立BloomFilter索引:

    1. CREATE TABLE lxw1234_orc2 stored AS ORC
    2. TBLPROPERTIES
    3. ('orc.compress'='SNAPPY',
    4. 'orc.create.index'='true',
    5. "orc.bloom.filter.columns"="pcid",
    6. 'orc.bloom.filter.fpp'='0.05',
    7. 'orc.stripe.size'='10485760',
    8. 'orc.row.index.stride'='10000')
    9. AS
    10. SELECT CAST(siteid AS INT) AS id,
    11. pcid
    12. FROM lxw1234_text
    13. DISTRIBUTE BY id sort BY id;

    然后执行上面的查询:

    1. SET hive.optimize.index.filter=true;
    2. SELECT COUNT(1) FROM lxw1234_orc1 WHERE id >= 0 AND id <= 1000
    3. AND pcid IN ('0005E26F0DCCDB56F9041C','A');

    orc index


    您可以关注 lxw的大数据田地 ,或者 加入邮件列表 ,随时接收博客更新的通知邮件。

     

    通过Row Group Index和Bloom Filter Index的双重索引优化,这条语句最终执行,只扫描了60000条记录,大大节省了MapTask的执行时间和资源。

    之前的文章《更高的压缩比,更好的性能–使用ORC文件格式优化Hive》中介绍了Hive的ORC文件格式,它不但有着很高的压缩比,节省存储和计算资源之外,还通过一个内置的轻量级索引,提升查询的性能。这个内置的轻量级索引,就是下面所说的Row Group Index。

    其实ORC支持的索引不止这一种,还有一种BloomFilter索引,两者结合起来,更加提升了Hive中基于ORC的查询性能。

    说明一下:本文使用Hive2.0.0 + hadoop-2.3.0-cdh5.0.0作为测试环境。表lxw1234_text为text格式保存,总记录数为12000920。

    Row Group Index

    由之前的文章知道,一个ORC文件包含一个或多个stripes(groups of row data),每个stripe中包含了每个columnmin/max值的索引数据,当查询中有<,>,=的操作时,会根据min/max值,跳过扫描不包含的stripes

    而其中为每个stripe建立的包含min/max值的索引,就称为Row Group Index,也叫min-max Index,或者Storage Index。在建立ORC格式表时,指定表参数’orc.create.index’=’true’之后,便会建立Row Group Index,需要注意的是,为了使Row Group Index有效利用,向表中加载数据时,必须对需要使用索引的字段进行排序,否则,min/max会失去意义。另外,这种索引通常用于数值型字段的查询过滤优化上。

    看下面的例子:

    1. CREATE TABLE lxw1234_orc2 stored AS ORC
    2. TBLPROPERTIES
    3. ('orc.compress'='SNAPPY',
    4. 'orc.create.index'='true',
    5. 'orc.bloom.filter.fpp'='0.05',
    6. 'orc.stripe.size'='10485760',
    7. 'orc.row.index.stride'='10000')
    8. AS
    9. SELECT CAST(siteid AS INT) AS id,
    10. pcid
    11. FROM lxw1234_text
    12. DISTRIBUTE BY id sort BY id;

    直接执行下面的查询(未使用索引):

    1. SELECT COUNT(1) FROM lxw1234_orc1 WHERE id >= 1382 AND id <= 1399;

    orc index

    很明显,扫描了所有记录。再使用索引查询:

    1. set hive.optimize.index.filter=true;
    2. SELECT COUNT(1) FROM lxw1234_orc1 WHERE id >= 1382 AND id <= 1399;

    orc index

    可以看到,只扫描了部分记录,即根据Row Group Index中的min/max跳过了WHERE条件中不包含的stripes,索引有效果。

    假如有下面的查询:

    1. SET hive.optimize.index.filter=true;
    2. SELECT COUNT(1) FROM lxw1234_orc1 WHERE id >= 0 AND id <= 1000
    3. AND pcid IN ('0005E26F0DCCDB56F9041C','A');

    执行的过程大概是这样的:

    先根据Row Group Index中的min/max,判断哪些stripes/file包含在内,接着逐行扫描,过滤pcid IN (‘0005E26F0DCCDB56F9041C’,’A’)的记录。

    orc index

    可以看到,没有全表扫描,跳过了一部分stripes。这样看来,如果where后面的id范围很大,完全可能会包含所有的文件,再根据pcid过滤时候,又相当于全表扫描了。

    对于这种查询场景的优化策略,就是下面的BloomFilter索引。

    Bloom Filter Index

    之前有篇文章《大数据去重统计之BloomFilter》,介绍过BloomFilter的原理和Java版的例子。Hive的ORC中基于此,提供了BloomFilter索引,用于性能优化。

    在建表时候,通过表参数”orc.bloom.filter.columns”=”pcid”来指定为那些字段建立BloomFilter索引,这样,在生成数据的时候,会在每个stripe中,为该字段建立BloomFilter的数据结构,当查询条件中包含对该字段的=号过滤时候,先从BloomFilter中获取以下是否包含该值,如果不包含,则跳过该stripe.

    看下面的建表语句,为pcid字段建立BloomFilter索引:

    1. CREATE TABLE lxw1234_orc2 stored AS ORC
    2. TBLPROPERTIES
    3. ('orc.compress'='SNAPPY',
    4. 'orc.create.index'='true',
    5. "orc.bloom.filter.columns"="pcid",
    6. 'orc.bloom.filter.fpp'='0.05',
    7. 'orc.stripe.size'='10485760',
    8. 'orc.row.index.stride'='10000')
    9. AS
    10. SELECT CAST(siteid AS INT) AS id,
    11. pcid
    12. FROM lxw1234_text
    13. DISTRIBUTE BY id sort BY id;

    然后执行上面的查询:

    1. SET hive.optimize.index.filter=true;
    2. SELECT COUNT(1) FROM lxw1234_orc1 WHERE id >= 0 AND id <= 1000
    3. AND pcid IN ('0005E26F0DCCDB56F9041C','A');

    orc index


    您可以关注 lxw的大数据田地 ,或者 加入邮件列表 ,随时接收博客更新的通知邮件。

     

    通过Row Group Index和Bloom Filter Index的双重索引优化,这条语句最终执行,只扫描了60000条记录,大大节省了MapTask的执行时间和资源。

  • 相关阅读:
    【2018.05.05 C与C++基础】C++中的自动废料收集:概念与问题引入
    【2018.04.27 C与C++基础】关于switch-case及if-else的效率问题
    【2018.04.19 ROS机器人操作系统】机器人控制:运动规划、路径规划及轨迹规划简介之一
    March 11th, 2018 Week 11th Sunday
    March 10th, 2018 Week 10th Saturday
    March 09th, 2018 Week 10th Friday
    March 08th, 2018 Week 10th Thursday
    March 07th, 2018 Week 10th Wednesday
    ubantu之Git使用
    AMS分析 -- 启动过程
  • 原文地址:https://www.cnblogs.com/wujin/p/6405355.html
Copyright © 2011-2022 走看看