Hatena::ブログ(Diary)

ablog このページをアンテナに追加 RSSフィード

2018-11-04

Parquet ファイルに Presto でクエリ時の Column Projection について調べた

確認したかったこと

  • Parquet ファイルに対して Presto で select count(year) のように特定カラムのみ参照するとそのカラムのみをストレージから読んでいる。
  • select count(*) すると Parquet ファイルのフッターのメタデータ(Row group の num rows)のみをストレージから読んでいる。

検証シナリオ

#クエリ
1select count(*) from amazon_reviews_parquet
2select count(year) from amazon_reviews_parquet
3select count(review_body) from amazon_reviews_parquet
4select * from amazon_reviews_parquet limit 10000
5select year from amazon_reviews_parquet limit 10000
6select review_body from amazon_reviews_parquet limit 10000

検証ポイント

Presto のスキャンサイズ
システムコール
$ sudo iotop
$ sudo csysdig
Linux カーネルのブロックレイヤーI/O
  • iostat で見たI/O量が select count(year) より select count(review_body) のほうが多いこと
  • blktrace + btt で見たI/O量が select count(year) より select count(review_body) のほうが多いこと
$ sudo mount -t debugfs none /sys/kernel/debug
$ sudo blktrace -w 60 -d /dev/nvme1n1p2 -o nvme1n1p2
$ sudo btt -i nvme1n1p2.blktrace.0 -B nvme1n1p2.blktrace.0.btt
ハイパーバイザーレイヤーI/O
  • EC2I/O 量が select count(year) より select count(review_body) のほうが多いこと
観測面から見える実装
$ ps -u hdfs
$ sudo ~/perf-map-agent/bin/perf-java-top <PID>
ソースコードの実装
  • Presto から HDFS に対してリクエストを出すコード
  • HDFS のランダムアクセスAPI
  • HDFSファイルシステムからランダムアクセスするコード
  • Sさんに教えてもらったやつ

環境


参考

  • Parquet ファイルの定義
$ aws s3 cp s3://amazon-reviews-pds/parquet/product_category=Apparel/part-00000-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet ./
$ java -jar parquet-tools-1.6.0.jar meta ~/part-00000-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
file:              file:/Users/azekyohe/part-00000-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
creator:           parquet-mr version 1.8.2 (build c6522788629e590a53eb79874b95f6c3ff11f16c)
extra:             org.apache.spark.sql.parquet.row.metadata = {"type":"struct","fields":[{"name":"marketplace","type":"string","nullable":true,"metadata":{}},{"name":"customer_id","type":"string","nullable":true,"metadata":{}},{"name":"review_id","type":"string","nullable":true,"metadata":{}},{"name":"product_id","type":"string","nullable":true,"metadata":{}},{"name":"product_parent","type":"string","nullable":true,"metadata":{}},{"name":"product_title","type":"string","nullable":true,"metadata":{}},{"name":"star_rating","type":"integer","nullable":true,"metadata":{}},{"name":"helpful_votes","type":"integer","nullable":true,"metadata":{}},{"name":"total_votes","type":"integer","nullable":true,"metadata":{}},{"name":"vine","type":"string","nullable":true,"metadata":{}},{"name":"verified_purchase","type":"string","nullable":true,"metadata":{}},{"name":"review_headline","type":"string","nullable":true,"metadata":{}},{"name":"review_body","type":"string","nullable":true,"metadata":{}},{"name":"review_date","type":"date","nullable":true,"metadata":{}},{"name":"year","type":"integer","nullable":true,"metadata":{}}]}

file schema:       spark_schema
--------------------------------------------------------------------------------
marketplace:       OPTIONAL BINARY O:UTF8 R:0 D:1
customer_id:       OPTIONAL BINARY O:UTF8 R:0 D:1
review_id:         OPTIONAL BINARY O:UTF8 R:0 D:1
product_id:        OPTIONAL BINARY O:UTF8 R:0 D:1
product_parent:    OPTIONAL BINARY O:UTF8 R:0 D:1
product_title:     OPTIONAL BINARY O:UTF8 R:0 D:1
star_rating:       OPTIONAL INT32 R:0 D:1
helpful_votes:     OPTIONAL INT32 R:0 D:1
total_votes:       OPTIONAL INT32 R:0 D:1
vine:              OPTIONAL BINARY O:UTF8 R:0 D:1
verified_purchase: OPTIONAL BINARY O:UTF8 R:0 D:1
review_headline:   OPTIONAL BINARY O:UTF8 R:0 D:1
review_body:       OPTIONAL BINARY O:UTF8 R:0 D:1 ★
review_date:       OPTIONAL INT32 O:DATE R:0 D:1
year:              OPTIONAL INT32 R:0 D:1 ★

row group 1:       RC:589900 TS:192293412 OFFSET:4
--------------------------------------------------------------------------------
marketplace:        BINARY SNAPPY DO:0 FPO:4 SZ:231/221/0.96 VC:589900 ENC:RLE,BIT_PACKED,PLAIN_DICTIONARY
customer_id:        BINARY SNAPPY DO:0 FPO:235 SZ:4581545/6957912/1.52 VC:589900 ENC:RLE,PLAIN,BIT_PACKED
review_id:          BINARY SNAPPY DO:0 FPO:4581780 SZ:8637455/10463253/1.21 VC:589900 ENC:RLE,PLAIN,BIT_PACKED
product_id:         BINARY SNAPPY DO:0 FPO:13219235 SZ:5034158/8259079/1.64 VC:589900 ENC:RLE,PLAIN,BIT_PACKED
product_parent:     BINARY SNAPPY DO:0 FPO:18253393 SZ:5187236/7484331/1.44 VC:589900 ENC:RLE,PLAIN,BIT_PACKED,PLAIN_DICTIONARY
product_title:      BINARY SNAPPY DO:0 FPO:23440629 SZ:21585566/34792104/1.61 VC:589900 ENC:RLE,PLAIN,BIT_PACKED,PLAIN_DICTIONARY
star_rating:        INT32 SNAPPY DO:0 FPO:45026195 SZ:221797/221763/1.00 VC:589900 ENC:RLE,BIT_PACKED,PLAIN_DICTIONARY
helpful_votes:      INT32 SNAPPY DO:0 FPO:45247992 SZ:276866/558457/2.02 VC:589900 ENC:RLE,BIT_PACKED,PLAIN_DICTIONARY
total_votes:        INT32 SNAPPY DO:0 FPO:45524858 SZ:306153/590359/1.93 VC:589900 ENC:RLE,BIT_PACKED,PLAIN_DICTIONARY
vine:               BINARY SNAPPY DO:0 FPO:45831011 SZ:962/1025/1.07 VC:589900 ENC:RLE,BIT_PACKED,PLAIN_DICTIONARY
verified_purchase:  BINARY SNAPPY DO:0 FPO:45831973 SZ:62135/74471/1.20 VC:589900 ENC:RLE,BIT_PACKED,PLAIN_DICTIONARY
review_headline:    BINARY SNAPPY DO:0 FPO:45894108 SZ:8309372/14205327/1.71 VC:589900 ENC:RLE,PLAIN,BIT_PACKED,PLAIN_DICTIONARY
review_body:        BINARY SNAPPY DO:0 FPO:54203480 SZ:66263112/107760057/1.63 VC:589900 ENC:RLE,PLAIN,BIT_PACKED
review_date:        INT32 SNAPPY DO:0 FPO:120466592 SZ:70391/738861/10.50 VC:589900 ENC:RLE,BIT_PACKED,PLAIN_DICTIONARY
year:               INT32 SNAPPY DO:0 FPO:120536983 SZ:9111/186192/20.44 VC:589900 ENC:RLE,BIT_PACKED,PLAIN_DICTIONARY

準備手順

データを S3 から HDFS にコピーする
$ ssh -i ~/mykey.pem hadoop@ec2-**-***-***-233.compute-1.amazonaws.com
  • hdfs ユーザーにスイッチする。
$ sudo su - hdfs
$ hadoop fs -mkdir /amazon-reviews-pds
  • データを S3 から HDFS にコピーする。
$ nohup s3-dist-cp --src  s3://amazon-reviews-pds/ --dest /amazon-reviews-pds  &
外部テーブルを定義する。
$ hive
> create database if not exists parquet;
^H> show databases;
> use parquet;
  • テーブルを作成する。
> CREATE EXTERNAL TABLE parquet.amazon_reviews_parquet(
  marketplace string, 
  customer_id string, 
  review_id string, 
  product_id string, 
  product_parent string, 
  product_title string, 
  star_rating int, 
  helpful_votes int, 
  total_votes int, 
  vine string, 
  verified_purchase string, 
  review_headline string, 
  review_body string, 
  review_date bigint, 
  year int)
PARTITIONED BY (product_category string)
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
  'hdfs:///amazon-reviews-pds/parquet';
> MSCK REPAIR TABLE parquet.amazon_reviews_parquet;
> quit;
  • クエリを実行できることを確認する。
$ presto-cli
presto> use hive.parquet;
presto:parquet> select count(*) from amazon_reviews_parquet;
presto:parquet> select count(year) from amazon_reviews_parquet;
presto:parquet> select count(review_body) from amazon_reviews_parquet;

性能情報取得ツールインストール
$ sudo yum -y install htop sysstat dstat iotop ltrace strace perf blktrace gnuplot
$ sudo yum -y install cmake
$ git clone --depth=1 https://github.com/jrudolph/perf-map-agent
$ cd perf-map-agent
$ cmake .
$ make
  • FlameGraph
$ git clone https://github.com/brendangregg/FlameGraph
$ chmod +x FlameGraph/*.pl
$ vi ~/.bashrc
export FLAMEGRAPH_DIR=~/FlameGraph

*1VPN経由でアクセスできない

2018-09-29

Prestoでparquetファイルにクエリをかける

  • データをコピーする
$ s3-dist-cp --src s3://amazon-reviews-pds/parquet/ --dest /amazon-reviews-pds/parquet/
$ hadoop fs -ls /amazon-reviews-pds/parquet/|head -10
Found 43 items
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Apparel
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Automotive
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Baby
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Beauty
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:14 /amazon-reviews-pds/parquet/product_category=Books
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:11 /amazon-reviews-pds/parquet/product_category=Camera
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Digital_Ebook_Purchase
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:15 /amazon-reviews-pds/parquet/product_category=Digital_Music_Purchase
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:15 /amazon-reviews-pds/parquet/product_category=Digital_Software
  • hive shell を起動する。
$ hive
  • テーブルを作成する
hive> CREATE EXTERNAL TABLE parquet.amazon_reviews_parquet(
  marketplace string, 
  customer_id string, 
  review_id string, 
  product_id string, 
  product_parent string, 
  product_title string, 
  star_rating int, 
  helpful_votes int, 
  total_votes int, 
  vine string, 
  verified_purchase string, 
  review_headline string, 
  review_body string, 
  review_date bigint, 
  year int)
PARTITIONED BY (product_category string)
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
  'hdfs:///amazon-reviews-pds/parquet';
hive> MSCK REPAIR TABLE parquet.amazon_reviews_parquet;
  • hive shell を終了する
hive> quit

Presto からクエリを投げてみる

# echo 3 > /proc/sys/vm/drop_caches
  • presto-cli を起動する
$ presto-cli
presto> use hive.parquet;
presto:parquet> select count(*) from amazon_reviews_parquet;
   _col0
-----------
 160796570
(1 row)

Query 20181008_103006_00003_ypxzu, FINISHED, 2 nodes
Splits: 1,126 total, 1,126 done (100.00%)
0:03 [161M rows, 0B] [49.9M rows/s, 0B/s]
presto:parquet> select count(year) from amazon_reviews_parquet;
   _col0
-----------
 160796570
(1 row)

Query 20181008_103037_00004_ypxzu, FINISHED, 2 nodes
Splits: 1,132 total, 1,132 done (100.00%)
0:05 [161M rows, 2.58MB] [31.2M rows/s, 513KB/s]
presto:parquet> select count(review_body) from amazon_reviews_parquet;
   _col0
-----------
 160789772
(1 row)

Query 20181008_103111_00005_ypxzu, FINISHED, 2 nodes
Splits: 1,137 total, 1,137 done (100.00%)
3:58 [161M rows, 34GB] [675K rows/s, 146MB/s]

f:id:yohei-a:20180930153032p:image:w640


f:id:yohei-a:20180930153026p:image:w640


計測

# echo 3 > /proc/sys/vm/drop_caches

インストール

$ sudo  yum -y install iotop
$ sudo yum -y install htop

データ

$ hadoop fs -ls -h -R /amazon-reviews-pds/parquet/|head -50
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Apparel
-rw-r--r--   1 hadoop hadoop    115.0 M 2018-09-29 20:11 /amazon-reviews-pds/parquet/product_category=Apparel/part-00000-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    115.3 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Apparel/part-00001-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    114.9 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Apparel/part-00002-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    115.2 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Apparel/part-00003-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    115.3 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Apparel/part-00004-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    115.3 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Apparel/part-00005-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    115.4 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Apparel/part-00006-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    114.8 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Apparel/part-00007-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    115.3 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Apparel/part-00008-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    115.3 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Apparel/part-00009-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Automotive
-rw-r--r--   1 hadoop hadoop     80.8 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Automotive/part-00000-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     81.2 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Automotive/part-00001-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     80.9 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Automotive/part-00002-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     81.1 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Automotive/part-00003-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     81.1 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Automotive/part-00004-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     80.8 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Automotive/part-00005-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     81.1 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Automotive/part-00006-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     80.6 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Automotive/part-00007-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     80.9 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Automotive/part-00008-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     81.3 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Automotive/part-00009-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Baby
-rw-r--r--   1 hadoop hadoop     48.9 M 2018-09-29 20:11 /amazon-reviews-pds/parquet/product_category=Baby/part-00000-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     49.5 M 2018-09-29 20:11 /amazon-reviews-pds/parquet/product_category=Baby/part-00001-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     49.3 M 2018-09-29 20:11 /amazon-reviews-pds/parquet/product_category=Baby/part-00002-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     49.0 M 2018-09-29 20:11 /amazon-reviews-pds/parquet/product_category=Baby/part-00003-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     49.1 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Baby/part-00004-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     49.1 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Baby/part-00005-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     49.3 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Baby/part-00006-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     49.0 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Baby/part-00007-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     49.0 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Baby/part-00008-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop     48.9 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Baby/part-00009-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Beauty
-rw-r--r--   1 hadoop hadoop    127.1 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Beauty/part-00000-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    127.3 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Beauty/part-00001-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    127.2 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Beauty/part-00002-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    126.9 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Beauty/part-00003-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    127.0 M 2018-09-29 20:12 /amazon-reviews-pds/parquet/product_category=Beauty/part-00004-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    127.0 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Beauty/part-00005-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    126.8 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Beauty/part-00006-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    127.0 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Beauty/part-00007-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    127.4 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Beauty/part-00008-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop    127.5 M 2018-09-29 20:13 /amazon-reviews-pds/parquet/product_category=Beauty/part-00009-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
drwxr-xr-x   - hadoop hadoop          0 2018-09-29 20:14 /amazon-reviews-pds/parquet/product_category=Books
-rw-r--r--   1 hadoop hadoop      1.0 G 2018-09-29 20:14 /amazon-reviews-pds/parquet/product_category=Books/part-00000-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop      1.0 G 2018-09-29 20:14 /amazon-reviews-pds/parquet/product_category=Books/part-00001-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop      1.0 G 2018-09-29 20:15 /amazon-reviews-pds/parquet/product_category=Books/part-00002-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop      1.0 G 2018-09-29 20:15 /amazon-reviews-pds/parquet/product_category=Books/part-00003-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet
-rw-r--r--   1 hadoop hadoop      1.0 G 2018-09-29 20:15 /amazon-reviews-pds/parquet/product_category=Books/part-00004-495c48e6-96d6-4650-aa65-3c36a3516ddd.c000.snappy.parquet

2018-09-24

HDFS の I/O サイズ

emr-5.17.0 で /etc/hadoop/conf/core-site.xml を確認すると以下の通り*1

  <property>
    <name>io.file.buffer.size</name>
    <value>65536</value>
  </property>

Note that HDFS Readers do not read whole blocks of data at a time, and instead stream the data via a buffered read (64k-128k typically). That the block size is X MB does not translate into a memory requirement unless you are explicitly storing the entire block in memory when streaming the read.

Solved: Hadoop read IO size - Cloudera Community
  @Override
  public FSDataInputStream open(Path f, final int bufferSize)
      throws IOException {
    statistics.incrementReadOps(1);
    Path absF = fixRelativePart(f);
    return new FileSystemLinkResolver<FSDataInputStream>() {
      @Override
      public FSDataInputStream doCall(final Path p)
          throws IOException, UnresolvedLinkException {
        final DFSInputStream dfsis =
          dfs.open(getPathName(p), bufferSize, verifyChecksum);
        return dfs.createWrappedInputStream(dfsis);
      }
      @Override
      public FSDataInputStream next(final FileSystem fs, final Path p)
          throws IOException {
        return fs.open(p, bufferSize);
      }
    }.resolve(this, absF);
  }
https://github.com/cloudera/hadoop-common/blob/cdh5.4.5-release/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DistributedFileSystem.java#L294-L303

これは, 各 Mapper は独立にシーケンシャル I/Oバッファサイズ単位(注4)で発行しているため, ディスクドライブに対しては完全なシーケンシャルアクセスにはならず, Mapper 数(同時 I/O ストリーム数) の増加により, シーケンシャリティは低下するためだと考えられる. つまり, 前述の性能律速は, 複数ストリーム I/O によるディスクシークの増加から起因される問題であると考えられる.

一般的に, 前述のような複数ストリーム I/O による性能律速の問題に対しては, I/O バッファサイズの増加, または, I/Oスケジューリングにより解決が図られる. 以下に, それぞれの解決策を Hadoop において検証した結果を示す.図 5 に I/O バッファサイズを変化させた時の I/O 転送レートを示す. I/O バッファサイズの増加に伴い, I/O 転送レートが低下の傾向にあることがわかる. また, 32MB の時は, 大きな性能低下が確認された. これは, 各 Mapper の逐次的な I/O処理モデル(注5) が起因していると考えられる. つまり, 小さい単位で I/O を発行した場合は, I/O 発行の間隔が短いことからOS の先読み機構が効率的に機能し, ディスクドライブに対するシーケンシャリティの増加に加えて, I/O 処理が CPU 処理にオーバーラップして実行される可能性が高いが, 大きい単位で I/O を発行した場合は, ディスクドライブに対するシーケンシャリティは増加するものの, I/O 発行の間隔が長いため OSの先読み機構が効率的に機能せず, I/O 処理と CPU 処理が逐次的に処理されるため, 小さい単位で I/O を発行した場合と比べて性能が低下してしまうと考えられる. このことから, 現状の HadoopI/O 処理モデルでは, I/O バッファサイズの増加のアプローチは当該問題に対する解決策とはならないと考えられる.

(注4):デフォルトは 4KB.

(注5):Hadoop の各 Mapper は I/O 処理と CPU 処理を同時には実行せず,逐次的に実行することで処理を進めるデータ処理アーキテクチャとなっている.

(注6):Hadoop は, 通常 HDFS のブロックを Spilt とし, Split ごとに Mapperを割り当てて処理を進める.

f:id:yohei-a:20180924183353p:image:w640

並列データインテンシブ処理基盤のI/O性能評価に関する実験的考察

HDFS キャッシング

HDFS のブロックはファイルシステムに保存されるため、Linux カーネルのページキャッシュを自然に使っていたが、ユーザー空間から制御できないため、HDFSキャッシングHadoop 2.3.0 以降)という機能がある。

HDFS上のデータの読み書きの際には、ディスクから読み出されたデータは、Linuxカーネル内のページキャッシュ(原文ではBuffer cacheとなってます)にキャッシュされます。(これにより毎回ディスクアクセスを避けることが期待できます)

HDFSが高速に?キャッシュメカニズムの追加 | Tech Blog

Hadoop 2.3.0 以降には「HDFSキャッシング」と呼ばれる、HDFSキャッシュ機構が搭載されています。

(中略)

HDFSの中央キャッシュ管理は、ユーザが明示的に指定したパスを、HDFSによって明示的にキャッシュする仕組みです。ネームノードはブロックをディスクに持つデータノード通信して、そのブロックを「オフピーク (off-heap)」キャッシュキャッシュします。

オフピークキャッシュは各データノードにある、JVMVMヒープ対象外のメモリ領域です。ユーザーがコマンドからキャッシュに登録するパスを指定することにより、ブロックがこの領域にキャッシュされます。

HDFSの新しい機能 - HDFSキャッシング | Tech Blog

https://www.ibm.com/support/knowledgecenter/ja/SSPT3X_4.1.0/com.ibm.swg.im.infosphere.biginsights.dev.doc/doc/biga_hdfscache.html を参考に手元の EMR(emr-5.17.0) のマスターノードで、hdfs-site.xmldfs.client.mmap.enabled や dfs.datanode.max.locked.memory のエントリはなく、キャッシュ・プールも無かったので、意図的に使わないと使われない模様。

$ hdfs cacheadmin -listPools
Found 0 results.

*1:マスターノードとコアノードで確認した

2018-09-23

PySpark から Parquet ファイル on HFDS にクエリを実行してみる

準備

$ ssh -i ~/us-east-1.pem hadoop@ec2-**-***-**-**.compute-1.amazonaws.com
$ hadoop fs -mkdir /amazon-reviews-pds-az/
$ s3-dist-cp --src s3://amazon-reviews-pds/ --dest /amazon-reviews-pds-az/
  • コピーしたファイルを確認する。
$ hadoop fs -ls -h -R /amazon-reviews-pds-az

実行

  • 以下のコードを実行する。
from pyspark.sql.types import *

df = sqlContext.read.parquet("/amazon-reviews-pds-az/parquet/")
df.createOrReplaceTempView("reviews")

print sqlContext.sql("SELECT * FROM reviews where product_category == 'Books'").count()

f:id:yohei-a:20180924023501p:image:w640


備忘録

# echo 3 > /proc/sys/vm/drop_caches
$ free
$ iostat -tx 5 | awk '{print strftime("%y-%m-%d %H:%M:%S"), $0}'|grep xvdb > /home/hadoop/iostat-`hostname`-1.log &
  • パターン1
from pyspark.sql.types import *
df = sqlContext.read.parquet("/amazon-reviews-pds-az/parquet/")
df.createOrReplaceTempView("reviews")
print sqlContext.sql("SELECT * FROM reviews").count()
  • パターン2
from pyspark.sql.types import *
df = sqlContext.read.parquet("/amazon-reviews-pds-az/parquet/")
df.createOrReplaceTempView("reviews")
print sqlContext.sql("SELECT star_rating FROM reviews").count()

参考

2018-09-19

db tech showcase 2018 Day 1

年に一度のデータベース界の同窓会的なイベント db tech showcase 2018 Day 1 に参加してきた。写真は懇親会でのマグロ解体ショー。

f:id:yohei-a:20180920032213j:image:w640

小幡さん、おつかれさまでした!

f:id:yohei-a:20180920042610j:image:w640


以下は聴講したセッションのメモ。

顧客理解のためのDWHにおける、ビッグデータ品質マネジメント

概要
  • 講師: 木村 豊さん(楽天株式会社 - グローバルデータ統括部データサイエンス部)
  • 講師略歴: 大手電機メーカーにてソフトウェア開発者からデータサイエンティストに転身。データ関連ビジネスの立ち上げ等に関わった後楽天にてCustomerDNAの開発に従事。
  • 概要: 楽天で構築中のDWH、CustomerDNAの概要解説と、そこで実施しているデータ品質マネジメントの実例についてご紹介します。(資料非公開)
サマリ
  • DWHでどのようにデータ品質をチェックしているかというお話。
  • データ処理の部分だけでなく、データソースもきちんとテストする必要がある。
  • プロセス(データ処理部分)のテスト観点
    • 正確性: 仕様通りマッピング・変換されているか
    • 非重複性: ユニークになるべきデータの組み合わせがユニークになっているか
    • 完全性: 投入されるべきデーアが全て投入されているか
    • 一貫性: テーブル・パーティション同士の関連性が一貫しているか
  • 課題
    • 変更検知した場合のエスカレーション・コミュニケーションフローは別途必要。
    • 実データをテストに使っているため、ガバナンス・環境上の問題が起きやすい。
    • テスト実施コンピュートコストが高い(決して低くはない)。
質疑応答
  • ETLツールでも同じようなことができるのではないか?
    • データサイエンティストが使っていたチェック用のクエリをプロダクションに乗せている。
  • RDBの制約などの機能でチェックできるのではないか?
    • データサイズが大きいのでRDBではしんどい。
  • 何に時間が一番がかかるか?
    • データを知るのに時間がかかる。どこに何のデータがあるか。
  • データディクショナリを作っているか
    • 作っているが、変更が入るので最新には追いつかない。

Pgpool-IIではじめるPostgreSQLのクラスタ運用

f:id:yohei-a:20180920042400j:image:w640

概要
  • 講師: 石井 達夫さん(SRA OSS, Inc. 日本支社 - 取締役支社長 / PostgreSQLコミッター)
  • 講師略歴: 経営者でありながら現役のプログラマとして活動。日本人として始めて PostgreSQLコミッターになった。現在は、PostgreSQL専用ミドルウェアの Pgpool-II の開発に注力し、プロジェクトのオーガナイザーを努める。
  • 概要: PostgreSQLに組み込みのレプリケーション機能を使うと、データベースサーバを複数使ったクラスタが容易に構築できます。しかし、運用局面や、アプリケーションからの利用となると、単一のPostgreSQLサーバでは起こらないような事態や、一筋縄では行かない問題が発生しがちです。本講演では、PostgreSQLのクラスタ利用での注意点やはまりどころを解説し、次にPgpool-IIを使ってこうした問題をどのように解決できるかを、デモを交えて説明します。
スライド
  • To be uploaded
メモ
  • P.9 の絵は複数のサーバプロセスがあるが簡略化した絵になっている
  • P.11 一時テーブル、強いロックなどはスタンバイで使えない。
  • 2010年に PostgreSQL 9.0 でトランザクションログの非同期レプリケーションが実装され、その後同期レプリケーションが実装され、現在、マルチマスタレプリケーションやシャーディングが開発されている。
  • 参照だけスタンバイに接続する場合、アプリ側で振り分けを実装したり、参照でも一貫性を求めるものはマスターを見るなど考慮点が多いが、Pgpool-II はアプリに意識させなくてもよろしくやってくれる質実剛健な機能が豊富に揃っていると感じた。
  • 紹介されていた Pgpool-II とレプリケーションによる構成は「レプリケーション」というと Oracle では Data Guard と比較しそうになるが、災害対策ではなく同一サイトでの耐障害性対策としての機能が多く、Oracle でいうと RAC と比較するのが適切なケースもあると感じた*1。優劣の比較ではなく各機能がどんな課題を解決するためにあり、Oracle ではどの機能がソリューションになるかという意味での比較。

爆速データレイクがほしい人向けImpalaパフォーマンスチューニング

f:id:yohei-a:20180920042139j:image:w640

概要
  • 講師: 嶋内 翔さん(Cloudera 株式会社 - セールスエンジニア)
  • 講師略歴: 京都大学工学部卒業、NECでエンタープライズOSSのSI支援業務に従事。2011年にClouderaの最初の日本人社員として入社。サポートエンジニアとして3年勤めた後、セールスエンジニアとしてHadoopを中心としたビッグデータ基盤に関する豊富な経験を積む。監訳書に「Apache Sqoopクックブック」などがある。
  • 概要: Apache Hadoopのためのオープンソース分析データベース、Impalaのベストプラクティスをご紹介します。
スライド

Impala のパフォーマンス・チューニングI/Oノード通信を減らすのが肝で、Hive や Spark でも通用する話。小手先のクエリチューニングではなくデータ構造が命。PROFILE で時間ベースで分析しよう。といった内容で本質的で非常に分かりやすかった。Parquet の説明は今まで見た中で一番分かりやすかった。Impala は統計情報をベースにコストベースオプティマイザで動作しているとのこと、統計情報は Hive カタログに保存されているのだろうと思う。


分散DB Apache Kuduのアーキテクチャ - DBの性能と一貫性を両立させる仕組み「HybridTime」とは

f:id:yohei-a:20180920042256j:image:w640

概要
  • 講師:佐藤 貴彦さん(Cloudera 株式会社 - セールスエンジニア)
  • 講師略歴: 奈良先端技術大学院大学でネットワークの研究をし、インフラなど低レイヤーの技術が好きになる。卒業後はOracleで、データベースを中心にインフラ全般のコンサルティングなどを行う。その後、Basho TechnologyでNoSQL及び分散システムに触れ、現在はClouderaでHadoop関連技術を中心に、幅広く手がける。趣味はクライミング。共著で「絵で見てわかるITインフラの仕組み」を執筆。
  • 概要: Apache Kudu は分析系クエリに強いカラムナー型の分散データベースです。KuduはOLTPとOLAPの両方のワークロードに耐えられる、HTAPと呼ばれる種類のDBで、昨年の #dbts2017では、Kuduの「速さ」について紹介しました。KuduはBI/DWHなど分析向けのDBといったイメージが強い一方で、 元々はGoogleのSpanner論文など触発されて開発されており、地理位置が離れたノード間でも一貫性を担保する仕組みを持っています。その仕組の元にあるのが、「HybridTime」と呼ばれるDBの内部時計です。今回はHybridTimeについて、その論文を紹介しながら仕組みに触れ、どのような特性を持っているのか、なぜこれがKuduの「速さ」にもつながるのかについてお話したいと思います。
スライド
  • To be uploaded
  • Kudu はC++で書かれたストレージエンジンで Impala や Spark などから使うことができる HTAP なDB。Exadata のストレージサーバのように push down 機能がある。MVCC だが単一行でしか対応していない。

P.S.

MySQL 界隈の方々と二次会に行って MySQL の Performance Schema について質問したり、各社の運用事情など聞けて楽しかった。

*1:Data Guard も同一サイトの耐障害性対策としても使える