1. Tổng quan về Hive
Apache Hive là 1 kho dữ liệu (data warehouse) hỗ trợ người sử dụng có thể dễ dàng hơn trong việc quản lý và truy vấn đối với các tập dữ liệu lớn được lưu trữ trên các hệ thống lưu trữ phân tán (distributed storage). Hive được xây dựng dựa trên cơ sở của Apache Hadoop, nó cung cấp các tính năng chinh sau:
- Công cụ cho phép dễ dàng thực hiện tác vụ như trích xuất, vận chuyển và lưu trữ dữ liệu.
- Cơ chế để xử lý cho nhiều định dạng dữ liệu khác nhau.
- Truy cập tới dữ liệu dạng files được lưu trữ trực tiếp ở trong Apache HDFS hoặc đối với nhiều hệ thống lưu trữ dữ liệu khác như Apache HBase.
- Thực hiện query thông qua MapReduce.
Hive định nghĩa ra một ngôn ngữ truy vấn đơn giản có cú pháp gần giống với SQL (SQL-like query language) được gọi là HiveQL, nó cho phép người sử dụng đã quen thuộc với các truy vấn SQL thực hiện việc truy vấn dữ liệu. Ngoài ra ngôn ngữ này còn cho phép các lập trình viên người đã quen thuộc với MapReduce framework có thể nhúng các mappers và reducers cho chính họ viết ra để thực thi nhiều hơn nữa các phân tích phức tập mà không được hỗ trợ bởi các hàm đã có sẵn trong ngôn ngữ HiveQL. HiveQL cung có thể được mở rộng với các custom scalar functions (UDF’s), aggregations (UDAF’s) và các table funtions (UDTF’s)
Hive không yêu cầu dữ liệu phải được đọc và ghi dưới một định dạng của riêng Hive (Hive format). Hive hoạt động tốt trên Thrift và các định dạng dữ liệu riêng của người sử dụng.
Hive không được thiết kế để cho các giao dịch online (OLTP workloads) và không nên dùng cho các real-time queries và các cập nhật trên từng dòng trong 1 table (row-level). Hive hoạt động tốt nhất cho các batch jobs trên các tập dữ liệu lớn, mà ở đó dữ liệu được thêm vào liên tục (append-only data) ví dụ như web logs. Hive có khả năng mở rộng theo chiều ngang tốt (thực thi tốt trên 1 hadoop cluster có số tượng máy biến đổi), có khả năng tích hợp với MapReduce framework và UDF, UDAF, UDTF; có khả năng chống chịu lỗi và mềm dẻo đối với các dữ liệu đầu vào của chính nó.
Các thành phần cấu hình Hive bao gồm HCatalog và WebHCat. HCatalog là một thành phần của Hive. Đây là lớp quản lý lưu trữ cho Hadoop (table and management layer), nó cho phép người dùng với các công cụ xử lý dữ liệu khác nhau bao gồm cả Pig và MapReduce thực thi hoạt động đọc, ghi một cách dễ dàng hơn. WebHCat cung cấp một dịch vụ cho phép bạn có thể thực thi Hadoop MapReduce (hoặc YARN), Pig, Hive.
2.Kiến trúc của Hive
Hive có các thành phần chính là :
- Hive UI: cung cấp giao diện cho phép người sử dụng tương tác với hệ thống Hive. Hive cung cấp nhiều phương thức khác nhau cho phép người sử dụng tương tác với Hive:
- CLI: giao diện dạng shell cho phép người sử dụng tương tác trực tiếp qua command line.
- Hive Web Interface: giao diện Web cho phép người sử dụng thực hiện các truy vấn thông qua giao diện Web.
- Hive Thrift Server: cho phép các client từ nhiều ngôn ngữ lập trình khác nhau có thể thực hiện tương tác với Hive.
- Hive Driver: thành phần nhận các truy vấn và chuyển các truy vấn này thành các MapReduce Jobs để tiến hành xử lý yêu cầu của người sử dụng.
- Driver: nhận các truy vấn, thành phần này thực hiện việc quản lý các sessions và cung cấp các API để thực thi và lấy dữ liệu trên JDBC/ODBC interfaces.
- Compiler: thành phần hiện việc phân tích ngữ nghĩa đối với các query, lấy các thông tin metadata cần thiết về table và partion từ metastore để sinh ra các excution plan.
- Execute engine: thành phần thực thi các execution plan được tạo bởi compiler (submit các job tới MapReduce). Ngoài ra thành phần execution enginen này thực hiện việc quản lý các dependencies của các bước trong mỗi execution plan, thực thi từng bước này.
- Hive Metastore: thành phần lưu trữ các metadata của Hive: table, partion, buckets bao gồm cả thông tin về các column trong mỗi table, các serializers và desrializers cần thiết để thực hiện việc đọc và ghi dữ liệu. Metastore sử dụng một cơ sở dữ liệu quan hệ để lưu trữ dữ liệu của chính mình.
Hình 2.1. Kiến trúc của Hive
3. Hoạt động của Hive
Hình 3.1. Mô hình hoạt động của Hive
Quy trình hoạt động của Hive có thể được mô tả theo các bước sau:
- Các truy vấn tới từ User Interface (CLI, Hive Web Interface, Thirft Server) được gửi tới thành phần Driver (Bước 1 hình 3.1)
- Driver tạo ra mới 1 session cho truy vấn này và gửi query tới compiler để nhận lấy Execution Plan (Bước 2 hình 3.1)
- Compilter nhận các metadata cần thiết từ Metastore (Bước 3, 4 hình 3.1). Các metadata này sẽ được sử dụng để kiểm tra các biểu thức bên trong query mà Compiler nhận được.
- Plan được sinh ra bởi Compiler (thông tin về các job (map-reduce) cần thiết để thực thi query sẽ được gửi lại tới thành phần thực thi (Bước 5hình 3.1)
- Execution engine nhận yêu cầu thực thi và lấy các metadata cần thiết và yêu cầu mapreduce thực thi công việc (Bước 6.1, 6.2, 6.3 hình 3.1)
- Khi output được sinh ra, nó sẽ được ghi dưới dạng 1 temporary file, temorary file này sẽ cung cấp các thông tin cần thiết cho các stages khác của plan. Nội dung của các temporary file này được execution đọc trực tiếp từ HDFS như là 1 phần của các lời gọi từ Driver (bước 7, 8, 9 hình 3.1)
4. Mô hình dữ liệu trong Hive
Hình 4.1. Hive Data Model
Dữ liệu trong Hive được tổ chức thành các kiểu sau:
- Databases: là namespace cho các tables, dùng để nhóm và quản lý các nhóm tables khác nhau.
- Tables: tương tự như table trong các hệ cơ sở dữ liệu quan hệ. Trong Hive table có thể thực hiện các phép toán filter, join và union… Mặc định thì dữ liệu của Hive sẽ được lưu bên trong thư mục warehouse trên HDFS. Tuy nhiên Hive cũng cung cấp kiểu external table cho phép ta tạo ra và quản lý các table mà dữ liệu của nó đã tồn tại từ trước khi ta tạo ra table này hoặc nó được lưu trữ ở 1 thư mục khác bên trong hệ thống HDFS. Tổ chức row và column bên trong Hive có nhiều điểm tương đồng với tổ chức Row và Column trong các hệ cơ sở dữ liệu quan hệ. Hive có 2 kiểu table đó là: Managed Table và External tables.
- Partions: Mỗi table có thể có 1 hoặc nhiều các khóa mà từ đó xác định dữ liệu sẽ được lưu trữ ở đâu. Ví dụ table web_log có thể phân chia dữ liệu của mình theo từng ngày là lưu dữ liệu của mỗi ngày trong 1 thư mục khác nhau bên dưới đường dẫn warehouse. Ví dụ: /warehouse/web_log/date=”01-01-2014″
- Buckets: Dữ liệu trong mỗi partion có thể được phân chia thành nhiều buckets khác nhau dựa trên 1 hash của 1 colume bên trong table. Mỗi bucket lưu trữ dữ liệu của nó bên dưới 1 thư mục riêng. Việc phân chia các partion thành các bucket giúp việc thực thi các query dễ dàng hơn.
4.1. Managed Tables and External Tables
Managed Tables:
Khi bạn tạo mới 1 tables thì Hive sẽ chuyển các dữ liệu này tới tới kho dữ liệu của nó (warehouse directory). Tuy nhiên bạn vẫn có thể tạo ra các external table, với khai báo thì nàythì Hive biết rằng dữ liệu dữ liệu này đã tồn tại ở trên 1 location khác bên ngoài warehouse directory.
Sự khác biệt của chúng sẽ xảy ra ở 2 quá trình LOAD và DROP. Ta bắt đầu với việc tìm hiểu managed table trước tiên:
Khi bạn thực hiện việc load dữ liệu vào bên trong managed table, nó sẽ thực hiện việc chuyển dữ liệu tới bên trong warehouse directory. Ví dụ:
CREATE TABLE managed_table(dummy STRING); LOAD DATA INPATH '/user/hadoop/data.txt' INTO table managed_table; |
Với khai báo này thì Hive sẽ thực hiện việc di chuyển file hdfs://user/tom/data.txt tới Hive’s warehouse cho managed_table được lưu trữ tại đường dẫn:hdfs://user/hive/warehouse/managed_table.
Nếu table bị xóa đi với câu lệnh :
DROP TABLE managed_table; |
thì table bao gồm cả metadata và dữ liệu chứa bên trong table đó sẽ bị xóa đi, trong trường hợp này câu lện DROP sẽ thực hiện việc xóa dữ liệu và dữ liệu bên trong table trên sẽ không còn tồn tại nữa.
External tables:
External tables lại có cách đối xử khác biệt. Bạn sẽ quản lý việc tạo mới và xóa đi đối với dữ liệu. Địa chỉ của external data sẽ được khai báo khi tạo mới bảng:
CREATE EXTERNAL TABLE external_table (dummy STRING) LOCATION '/user/hadoop/external_table' ; LOAD DATA INPATH '/user/hadoop/data.txt' INTO TABLE external_table; |
Với từ khóa EXTERNAL, Hive hiểu rằng nó không trực tiếp quản lý các dữ liệu này bởi vậy nó sẽ không thực hiện việc di chuyển chúng tới Hive’s data warehouse. Trên thực tế là Hive không thực hiện việc kiểm tra xem dữ liệu trên External localtion có tồn tại hay không. Đây là 1 tiện ích khác hữu dụng, nó cho phép ta có thể thực hiện việc khởi tạo dữ liệu khi tạo 1 table trên Hive. Và khi dữ liệu việc drop 1 external table thì Hive chỉ thực hiện việc xóa đi các metadata của nó.
4.2. Partions and Buckets
Hive tổ chứng dữ liệu của nó thành các partions, là 1 cách để phân chia dữ liệu thành các khối khác nhau dựa trên giá trị của partion columns ví dụ như date. Sử dụng partions có thể khiến cho quá trình query trở nên nhan hơn/
Table hoặc partions cũng có thể tiếp tục phân chia thành các buckes, để giúp dữ liệu được tổ chức để sử dụng cho nhiều efficient query. Ví dụ, bucketing bởi userID có nghĩa là chúng ta cho thể thực hiện việc tính toán nhanh hơn trên mỗi query của người sử dụng thay vì thực hiện nó trên 1 tập dữ liệu được sắp xếp 1 cách ngẫu nhiên.
Partions:
Một table trong Hive có thể được partioned theo nhiều chiều khác nhau. Ví dụ như logs file có thể được partions bởi ngày nó được tạo ra và country để cho phép thực hiện các query theo location 1 cách dễ dàng hơn.
CREATE TABLE logs (ts BIGINT, line STRING) PARTITIONED BY (dt STRING, country STRING); |
Khi ta chuyển dữ liệu tới một partion talbe, thông tin về partion phải được xác định:
LOAD DATA LOCAL INPATH 'input/hive/partions/file1' INTO TABLE logs PARTITION (dt= '2001-01-01' , country= 'GB' ); |
Đối với mức filesystem thì các partion đơn giản là được lưu trữ lồng bên trong nhau trong thư mục lưu trữ dữ liệu cả table đó.
/user/hive/warehouse/logs/dt =2010-01-01 /country =GB /file1 /file2 /country =US /file3 /dt =2010-01-02 /country =GB /file4 /country =US /file5 /file6 |
Table logs có 2 partions được chia theo trường date, 2010-01-01 và 2010-01-02, chúng được lưu trữ tương ứng trong các đường dẫn có tên dt=2010-01-01 và dt=2010-01-02 và 2 subpartions GB và US được lưu trữ bên trong các date partions, chúng có tên: country=GB và country=US:
Chúng ta có thể kiểm tra các partions trong Hive bằng câu lệnh:
hive> SHOW PARTITIONS logs; dt= 2001 - 01 - 01 /country=GB dt= 2001 - 01 - 01 /country=US dt= 2001 - 01 - 02 /country=GB dt= 2001 - 01 - 02 /country=US |
Buckets
Có 2 lý do tại sao bạn nên tổ chức dữ liệu bên trong table (partions) thành các buckets. Điều đầu tiên là nó cho phép thực hiện các query 1 cách hiệu quả hơn. Bucketing tác động tới extra structure trên table. nó giúp Hive thực hiện các query 1 cách thuận lợi hơn. Ví dụ việc join giữa 2 table đã được bucked trên cùng 1 column – đã thực hiện việc join columns – có thể hiệu quả tương tự như map-side join.
Partion vs bucket:
- Partion thực hiện phân chia dữ liệu trong 1 table theo value của column key, mỗi partion key sẽ có 1 không gian lưu trữ của riêng nó.
- Bucketing: thực hiện việc phân phối các key tới từng bucket khác nhau và mỗi partion lại chỉ có 1 key duy nhất.
4.3. Các kiểu dữ liệu trong Hive
Kiểu dữ liệu nguyên thủy:
Mỗi columns có 1 kiểu dữ liệu cố định. Các kiểu dữ liệu nguyên thủy sau sẽ được hỗ trợ đối với Hive:
- Integers:
- TINYINT – 1 byte integer
- SMALLINT – 2 byte integer
- INT – 4 byte integer
- BIGINT – 8 byte integer
- Boolean type
- BOOLEAN – TRUE/FALSE
- Floating point numbers
- FLOAT – single precision
- DOUBLE – Double precision
- String type
- STRING – sequence of characters in a specified character set
Các kiểu dữ liệu khác:
- Structs: là kiểu dữ liệu mà mỗi phần tử bên trong đó có thể được truy cập thông qua việc sử dụng ký hiệu (.) . Ví dụ, với kiểu dữ liệu STRUCT {a INT; b INT} ví dụ trường a của nó có thể truy cập thông qua c.a
- Maps (key-value tuples): là kiểu dữ liệu mà các phần tử sẽ được truy cập thông qua ký hiệu [‘element name’]. Đối với map M thực hiện việc map dữ liệu đối với khóa ‘group’ -> thì dữ liệu sẽ được sử dụng bởi trường M[‘group’]
- Arrays (indexable lists): Kiểu mảng.
5.Metastore
The metastore là trung tâm lưu trữ của metadata của Hive. Metastore được thi thành 2 thành phần: a services và backing store dùng để lưu trữ dữ liệu. Mặc định thì metastore service chạy trong cùng 1 jvm với Hive services và bao gồm luôn cả 1 Derby database instances được lưu trữ trên local disk. Mô hình này được gọi là embedded metastore configuration.
Sử dụng embedded metastore là cách đơn giản nhất để bắt đầu với Hive, mặc dù 1 embedded Derby database chỉ cho phép truy cập vào files ở trên disk 1 lần ở cùng 1 thời điểm, điều đó có nghĩa là bạn chỉ có thể có 1 session duy nhất có thể sử dụng dữ liệu trong metastore. Nếu ta thử khởi động session số 2 thì sẽ gặp được thông báo lỗi
Hình 5.1. Hive Metastore
Giải pháp để hỗ trợ sử dụng nhiều session cùng 1 lúc là sử dụng standalone database. Cấu hình này còn được gọi tên là local mestastore, với nó thì metastore services vẫn tiếp tục chạy trong cùng 1 JVM với Hive services nhưng nó thực hiện kế t nối tới database thông qua 1 process khác, database này có thể nằm trên local machine hoặc trên remote machine. Bất kỳ JDBC-compliant database có thể được sử dụng bằng việc thiết lập thuộc tính javax.jdo.option.*.
MySQL là lựa chọn phổ biến cho việc lưu trữ standalone metastore. Trong trường hợp này javax.jdo.option.ConnectionURL sẽ được thiết lập là:jdbc:mysql://dbname?createDatabaseIfNotExist=true và javax.jdo.option.ConnectionDriverName được thiết lập thành com.mysql.jdbc.Driver. JDBC driver jar file cho MySQL phải được xuất hiện trong Hive’c classpath.
Còn một kiểu mô hình nữa là remote-metastore, trong đó 1 hay nhiều metastore server được chạy trên các process riêng biệt. Nó mang tới khả năng tốt hơn trong việc quản lý và đảm bảo tính an ninh.
Hình 5.2. Các cấu hình cho metastore
6. Một ví dụ về sử dụng Hive
Sau các phần trên, ta đã có cái nhìn khá tổng quát về Hive. Phần này sẽ thực hiện việc phân tích dữ liệu trong HDFS với Hive. Kịch bản sử dụng được đưa ra là ta sẽ sử dụng Hive để phân tích dữ liệu thu được từ các apache webserver được lưu trữ trên HDFS. Các file log này sẽ được thu thập từ các webserver bên trong hệ thống, và từ đó ta có thể thực hiện việc thống kê quá trình sử dụng trong hệ thống. Nội dung của 1 file Log sẽ có định dạng như sau:
64.242.88.10 - - [07 /Mar/2004 :16:05:49 -0800] "GET /twiki/bin/edit/Main/Double_bounce_sender?topicparent=Main.ConfigurationVariables HTTP/1.1" 401 12846 64.242.88.10 - - [07 /Mar/2004 :16:06:51 -0800] "GET /twiki/bin/rdiff/TWiki/NewUserTemplate?rev1=1.3&rev2=1.2 HTTP/1.1" 200 4523 64.242.88.10 - - [07 /Mar/2004 :16:10:02 -0800] "GET /mailman/listinfo/hsdivision HTTP/1.1" 200 6291 64.242.88.10 - - [07 /Mar/2004 :16:11:58 -0800] "GET /twiki/bin/view/TWiki/WikiSyntax HTTP/1.1" 200 7352 64.242.88.10 - - [07 /Mar/2004 :16:20:55 -0800] "GET /twiki/bin/view/Main/DCCAndPostFix HTTP/1.1" 200 5253 64.242.88.10 - - [07 /Mar/2004 :16:23:12 -0800] "GET /twiki/bin/oops/TWiki/AppendixFileSystem?template=oopsmore¶m1=1.12¶m2=1.12 HTTP/1.1" 200 11382 64.242.88.10 - - [07 /Mar/2004 :16:24:16 -0800] "GET /twiki/bin/view/Main/PeterThoeny HTTP/1.1" 200 4924 64.242.88.10 - - [07 /Mar/2004 :16:29:16 -0800] "GET /twiki/bin/edit/Main/Header_checks?topicparent=Main.ConfigurationVariables HTTP/1.1" 401 12851 64.242.88.10 - - [07 /Mar/2004 :16:30:29 -0800] "GET /twiki/bin/attach/Main/OfficeLocations HTTP/1.1" 401 12851 64.242.88.10 - - [07 /Mar/2004 :16:31:48 -0800] "GET /twiki/bin/view/TWiki/WebTopicEditTemplate HTTP/1.1" 200 3732 64.242.88.10 - - [07 /Mar/2004 :16:32:50 -0800] "GET /twiki/bin/view/Main/WebChanges HTTP/1.1" 200 40520 64.242.88.10 - - [07 /Mar/2004 :16:33:53 -0800] "GET /twiki/bin/edit/Main/Smtpd_etrn_restrictions?topicparent=Main.ConfigurationVariables HTTP/1.1" 401 12851 64.242.88.10 - - [07 /Mar/2004 :16:35:19 -0800] "GET /mailman/listinfo/business HTTP/1.1" 200 6379 64.242.88.10 - - [07 /Mar/2004 :16:36:22 -0800] "GET /twiki/bin/rdiff/Main/WebIndex?rev1=1.2&rev2=1.1 HTTP/1.1" 200 46373 64.242.88.10 - - [07 /Mar/2004 :16:37:27 -0800] "GET /twiki/bin/view/TWiki/DontNotify HTTP/1.1" 200 4140 64.242.88.10 - - [07 /Mar/2004 :16:39:24 -0800] "GET /twiki/bin/view/Main/TokyoOffice HTTP/1.1" 200 3853 64.242.88.10 - - [07 /Mar/2004 :16:43:54 -0800] "GET /twiki/bin/view/Main/MikeMannix HTTP/1.1" 200 3686 64.242.88.10 - - [07 /Mar/2004 :16:45:56 -0800] "GET /twiki/bin/attach/Main/PostfixCommands HTTP/1.1" 401 12846 |
Ta thực hiện lưu trữ file này dưới đường dẫn /user/logs/access.log.
Ta thực hiện việc tạo 1 Hive table để map với các dữ liệu này.
CREATE EXTERNAL TABLE request(address STRING, info STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '- -' LINES TERMINATED BY '\n' STORED AS TEXTFILE LOCATION '/user/logs/access.log' ; |
Trong đó:
- Dữ liệu trong access.log sẽ được map tới table “request”
- Table request gồm có 2 column là adress và info tất cả đều có kiểu là STRING.
- Các column được phân tách bằng nhóm ký hiệu “- -“, mỗi 1 line được đánh dấu kết thúc bằng ký hiệu “\n”
- Nơi chứa dữ liệu mà table request map tới là ”
/user/logs/access.log"
Nếu không có exception nào được đưa ra thì ta có thể bắt đầu thực hiện việc truy vấn dữ liệu bên trong Hive table. Một số truy vấn mẫu:
Liệt kê tất cả thông tin thu được từ trong các table:
SELECT * FROM request; |
Liệt kê các IP đã thực hiện truy cập tới:
SELECT DISTINCT address FROM request; |
Liệt kê số lượng request theo từng IP:
SELECT address, count( 1 ) FROM request GROUP BY address ORDER BY address DESC; |
Tài liệu tham khảo
1. Hadoop: The Definitive Guilde 2.0, Tom White, 2011
2. https://cwiki.apache.org/confluence/display/Hive/Home
Klik untuk melihat kode: :) =( :s :D :-D ^:D ^o^ 7:( :Q :p T_T @@, :-a :W *fck* x@