轉: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。ide

Row Group Index

由以前的文章知道,一個ORC文件包含一個或多個stripes(groups of row data),每一個stripe中包含了每一個columnmin/max值的索引數據,當查詢中有<,>,=的操做時,會根據min/max值,跳過掃描不包含的stripesoop

而其中爲每一個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,索引有效果。spa

假若有下面的查詢:htm

  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的執行時間和資源。

相關文章
相關標籤/搜索