Thời gian gần đây, mình phải làm việc với Apache Hive thường xuyên. Việc làm sao để thời gian thực hiện các câu query trên Hive ngắn hơn trở nên rất cần thiết. Dưới đây là tổng hợp một số cách cơ bản để cải thiện performance cho Hive queries.
1. Sử dụng Apache Tez execution engine
Thiết lập mặc định là Hive sẽ sử dụng Map-reduce engine để thực thi các câu query. Thay vào đó, ta có thể sử dụng Tez engine - tốc độ xử lý sẽ nhanh hơn rất nhiều khi ta dùng Map-reduce.
Nếu Tez chưa được setting thành query engine mặc định trên môi trường Hadoop thì ta có thể dùng Tez bằng cách chạy thiết lập sau khi bắt đầu Hive query
set hive.execution.engine=tez;
Và khi đó mọi câu Hive query sẽ được thực thi bằng Tez execution engine.
Ngoài ra, ta cũng có thể thiết lập Tez enginze thành execution engine mặc định cho Hive qua Ambari
Chi tiết về Tez có thể tham khảo tại: Tez Homepage
2. Dùng ORCFile
Lời khuyên từ Hotonwork là Store all data in ORCFile format.
Sau đây là 1 số điểm mạnh của ORCFile
- Nén dữ liệu hiệu quả
-
Tốc độ đọc nhanh: Với built-in index, min/max values, predicate pushdown, Bloom filters, ... giúp cho tốc độ đọc dữ liệu định dạng ORCFile nhanh
-
Đã được khẳng định trong các hệ thống lớn. Ví dụ: Facebook dùng ORC file format cho hệ thống 300+ PB dữ liệu
Để dùng ORCFile ta chỉ cần thêm STORED AS orc
vào cuối create table statements như sau
CREATE TABLE mytable (
...
) STORED AS orc;
Ta cũng có thể đơn giản chuyển data cũ sang dạng ORCFile bằng cách tạo 1 table copy như sau, rồi xóa table cũ đi.
CREATE TABLE a_orc STORED AS ORC AS SELECT * FROM A;
Bình thường ta có thể sử dụng setting mặc định cho ORCFile. Tuy nhiên một số trường hợp cần thay đổi, ta có thểm tham khảo bảng sau:
Key |
Default Setting |
Notes |
---|---|---|
orc.compress | ZLIB | Các kiểu nén (NONE, ZLIB, SNAPPY). |
orc.compress.size | 262,144 |
Số bytes trên mỗi block nén |
orc.stripe.size | 268,435,456 |
Số bytes trên mỗi stripe. |
orc.row.index.stride |
10,000 |
Số rows giữa các index entries (>= 1,000). |
orc.create.index |
true |
Có dùng index hay không |
orc.bloom.filter.columns |
-- | Danh sách các tên cột được ngăn cách bởi dấy phẩy "," dùng cho Bloom filter |
orc.bloom.filter.fpp |
0.05 |
Tỷ lệ sai cho phép của Bloom filter. Lớn hơn 0.0 và bé hơn 1.0. |
3. Dùng Vectorization
Vector hóa query execution giúp cải thiện hiệu năng của các phép toán như scans, aggregations, filters and joins bằng cách thực hiện chúng dưới dạng batch cho 1024 rows 1 lúc thay vì 1 rows
Ta có thể sử dụng dễ dàng bằng 2 setting sau
set hive.vectorized.execution.enabled = true;
set hive.vectorized.execution.reduce.enabled = true;
4. CBO - Cost-based optimization
Hive sẽ tối ưu kế hoạch thực thi câu query (cả về logical và physical) trước khi submit để thực thi nó.
Và Hive CBO giúp Hive tối ưu câu query dựa trên cost của câu query đó. Từ đó đưa ra các quyết định như thứ tự join như thế nào, kiểu join nào là tối ưu, mức độ thực thi song song, ...
Để dùng CBO ta có thể thiết lập các parameter sau trước khi bắt đầu query
set hive.cbo.enable=true;
set hive.compute.query.using.stats=true;
set hive.stats.fetch.column.stats=true;
set hive.stats.fetch.partition.stats=true;
Và ta phải chuẩn bị Column, table statistic
cho CBO. Chú ý rằng, dữ liệu statistics
của table chưa được tạo thì CBO sẽ bị tắt đi.
Dưới đây là 1 số câu lệnh để thu thập Column, Table Statistics
#1 Thu thập table statistics cho non-partitioned tables
ANALYZE TABLE [table_name] COMPUTE STATISTICS;
#2 Thu thập table statistics cho bảng được partition
ANALYZE TABLE [table_name] PARTITION(partition_column) COMPUTE STATISTICS;
#3 Thu thập column statistics
ANALYZE TABLE [table_name] COMPUTE STATISTICS for COLUMNS [comma_separated_column_list];
ANALYZE TABLE [table_name] PARTITION(partition_column) COMPUTE STATISTICS for COLUMNS [comma_separated_column_list];
Việc thu thập đầy đủ cả column statistics và table statistics là tốt nhất cho query performance.
5. Thiết kế Data Storage dùng Partitions
Partitions giúp cải thiện performance của câu Hive query bằng cách filter các partitioned columns. Từ đó ta chỉ phải scan dữ liệu trên 1 hoặc 1 số ít partition thỏa mãn điều kiện của filter. Một hệ thống lớn có thể có đến 10.000 partitions.
Ví dụ về partition
CREATE TABLE sale(id in, amount decimal)
PARTITIONED BY (xdate string, state string);
Sau đây là 1 số best practices với partitions
- Không partition với unique ID
- Kích thước trung bình của 1 partition nên lớn hơn hoặc bằng 1 GB
- Một câu query không nên xử lý hơn 1000 partitions
Kết luận
Trên đây là 1 số cách đơn giản và hay được sử dụng để cải thiện tốc độ query của Hive.
Và cuối cùng, những cách đấy sẽ không thể có hiệu quả nếu câu SQL của ta không được tốt. Hãy viết những câu SQL tốt, giúp cho Hive query tốt hơn, nhanh hơn.