HIVE是什么
來自度娘百科的解釋:hive是基於Hadoop的一個數據倉庫工具,可以將結構化的數據文件映射為一張數據庫表,並提供完整的sql查詢功能,可以將sql語句轉換為MapReduce任務進行運行。 其優點是學習成本低,可以通過類SQL語句快速實現簡單的MapReduce統計,不必開發專門的MapReduce應用,十分適合數據倉庫的統計分析。
簡單來說,就是用QL這種語言的方式來完成MapReduce程序的工作,由於大多數程序員都會寫基於關系型數據庫的SQL,那么HIVE的出現也就將Hadoop上的開發降低了很多門檻。
Hive常見的參數
io.sort.mb設置數據緩沖區的小大
HIVE基礎語句
創建表
Hive的表,與普通關系型數據庫,如mysql在表上有很大的區別,所有hive的表都是一個文件,它是基於Hadoop的文件系統來做的。
hive總體來說可以總結為三種不同類型的表。
1. 普通表
普通表的創建,如上所說,不講了。其中,一個表,就對應一個表名對應的文件。
2. 外部表
EXTERNAL 關鍵字可以讓用戶創建一個外部表,在建表的同時指定一個指向實際數據的路徑(LOCATION),Hive 創建內部表時,會將數據移動到數據倉庫指向的路徑;若創建外部表,僅記錄數據所在的路徑,不對數據的位置做任何改變。在刪除表的時候,內部表的元數據和數據會被一起刪除,而外部表只刪除元數據,不刪除數據。具體sql如下:
Java代碼
CREATE EXTERNAL TABLE test_1(id INT, name STRING, city STRING) SORTED BY TEXTFILE ROW FORMAT DELIMITED‘\t’ LOCATION ‘hdfs://../../..’
3. 分區表
有分區的表可以在創建的時候使用 PARTITIONED BY 語句。一個表可以擁有一個或者多個分區,每一個分區單獨存在一個目錄下。而且,表和分區都可以對某個列進行 CLUSTERED BY 操作,將若干個列放入一個桶(bucket)中。也可以利用SORT BY 對數據進行排序。這樣可以為特定應用提高性能。具體SQL如下:
Java代碼
CREATE TABLE test_1(id INT, name STRING, city STRING) PARTITIONED BY (pt STRING) SORTED BY TEXTFILE ROW FORMAT DELIMITED‘\t’
Hive的排序,因為底層實現的關系,比較不同於普通排序,這里先不講。桶的概念,主要是為性能考慮,可以理解為對分區內列,進行再次划分,提高性能。在底層,一個桶其實是一個文件。如果桶划分過多,會導致文件數量暴增,一旦達到系統文件數量的上限,就杯具了。哪種是最優數量,這個哥也不知道。
分區表實際是一個文件夾,表名即文件夾名。每個分區,實際是表名這個文件夾下面的不同文件。分區可以根據時間、地點等等進行划分。比如,每天一個分區,等於每天存每天的數據;或者每個城市,存放每個城市的數據。每次查詢數據的時候,只要寫下類似 where pt=2010_08_23這樣的條件即可查詢指定時間得數據。
總體而言,普通表,類似mysql的表結構,外部表的意義更多是指數據的路徑映射。分區表,是最難以理解,也是最hive最大的優勢。之后會專門針對分區表進行講解。
建表語句如下:
Java代碼
hive> CREATE TABLE pokes (foo INT, bar STRING);
實際示例
創建一個表
Java代碼
CREATE TABLE u_data (
userid INT,
movieid INT,
rating INT,
unixtime STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE;
其中,hive支持的字段類型,並不多,可以簡單的理解為數字類型和字符串類型,詳細列表如下:
TINYINT
SMALLINT
INT
BIGINT
BOOLEAN
FLOAT
DOUBLE
STRING
創建表並創建索引字段ds
Java代碼
hive> CREATE TABLE invites (foo INT, bar STRING) PARTITIONED BY (ds STRING);
顯示所有表
Java代碼
hive> SHOW TABLES;
按正條件(正則表達式)顯示表,
Java代碼
hive> SHOW TABLES '.*s';
表添加一列
Java代碼
hive> ALTER TABLE pokes ADD COLUMNS (new_col INT);
添加一列並增加列字段注釋
Java代碼
hive> ALTER TABLE invites ADD COLUMNS (new_col2 INT COMMENT 'a comment');
更改表名
Java代碼
hive> ALTER TABLE events RENAME TO 3koobecaf;
刪除列
Java代碼
hive> DROP TABLE pokes;
元數據存儲
Hive不支持一條一條的用insert語句進行插入操作,也不支持update的操作。數據是以load的方式,加載到建立好的表中。數據一旦導入,則不可修改。要么drop掉整個表,要么建立新的表,導入新的數據。
將文件中的數據加載到表中
Java代碼
hive> LOAD DATA LOCAL INPATH './examples/files/kv1.txt' OVERWRITE INTO TABLE pokes;
加載本地數據,同時給定分區信息
Java代碼
hive> LOAD DATA LOCAL INPATH './examples/files/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15');
加載DFS數據 ,同時給定分區信息
Java代碼
hive> LOAD DATA INPATH '/user/myname/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15');
The above command will load data from an HDFS file/directory to the table. Note that loading data from HDFS will result in moving the file/directory. As a result, the operation is almost instantaneous.
INSERT+SELECT
Standard syntax:
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement
Hive extension (multiple inserts):
FROM from_statement
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1
[INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2] ...
Hive extension (dynamic partition inserts):
INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement
這個的用法,和上面兩種直接沈陽最好的男科醫院操作file的方式,截然不同。排開分區
SQL 操作
按先件查詢
hive> SELECT a.foo FROM invites a WHERE a.ds='';
將查詢數據輸出至目錄
hive> INSERT OVERWRITE DIRECTORY '/tmp/hdfs_out' SELECT a.* FROM invites a WHERE a.ds='';
將查詢結果輸出至本地目錄
hive> INSERT OVERWRITE LOCAL DIRECTORY '/tmp/local_out' SELECT a.* FROM pokes a;
選擇所有列到本地目錄
hive> INSERT OVERWRITE TABLE events SELECT a.* FROM profiles a;
hive> INSERT OVERWRITE TABLE events SELECT a.* FROM profiles a WHERE a.key < 100;
hive> INSERT OVERWRITE LOCAL DIRECTORY '/tmp/reg_3' SELECT a.* FROM events a;
hive> INSERT OVERWRITE DIRECTORY '/tmp/reg_4' select a.invites, a.pokes FROM profiles a;
hive> INSERT OVERWRITE DIRECTORY '/tmp/reg_5' SELECT COUNT(1) FROM invites a WHERE a.ds='';
hive> INSERT OVERWRITE DIRECTORY '/tmp/reg_5' SELECT a.foo, a.bar FROM invites a;
hive> INSERT OVERWRITE LOCAL DIRECTORY '/tmp/sum' SELECT SUM(a.pc) FROM pc1 a;
將一個表的統計結果插入另一個表中
hive> FROM invites a INSERT OVERWRITE TABLE events SELECT a.bar, count(1) WHERE a.foo > 0 GROUP BY a.bar;
hive> INSERT OVERWRITE TABLE events SELECT a.bar, count(1) FROM invites a WHERE a.foo > 0 GROUP BY a.bar;
JOIN
hive> FROM pokes t1 JOIN invites t2 ON (t1.bar = t2.bar) INSERT OVERWRITE TABLE events SELECT t1.bar, t1.foo, t2.foo;
將多表數據插入到同一表中
FROM src
INSERT OVERWRITE TABLE dest1 SELECT src.* WHERE src.key < 100
INSERT OVERWRITE TABLE dest2 SELECT src.key, src.value WHERE src.key >= 100 and src.key < 200
INSERT OVERWRITE TABLE dest3 PARTITION(ds='2008-04-08', hr='12') SELECT src.key WHERE src.key >= 200 and src.key < 300
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/dest4.out' SELECT src.value WHERE src.key >= 300;
將文件流直接插入文件
Java代碼
hive> FROM invites a INSERT OVERWRITE TABLE events SELECT TRANSFORM(a.foo, a.bar) AS (oof, rab) USING '/bin/cat' WHERE a.ds > '2008-08-09';
This streams the data in the map phase through the script /bin/cat (like hadoop streaming). Similarly - streaming can be used on the reduce side (please see the Hive Tutorial or examples)
下載示例數據文件,並解壓縮
wget http://www.grouplens.org/system/files/ml-data.tar__0.gz
tar xvzf ml-data.tar__0.gz
加載數據到表中
Java代碼
LOAD DATA LOCAL INPATH 'ml-data/u.data'
OVERWRITE INTO TABLE u_data;
統計數據總量
Java代碼
SELECT COUNT(1) FROM u_data;
現在做一些復雜的數據分析
創建一個 weekday_mapper.py: 文件,作為數據按周進行分割
import sys
import datetime
for line in sys.stdin:
line = line.strip()
userid, movieid, rating, unixtime = line.split('\t')
生成數據的周信息
weekday = datetime.datetime.fromtimestamp(float(unixtime)).isoweekday()
print '\t'.join([userid, movieid, rating, str(weekday)])
使用映射腳本
//創建表,按分割符分割行中的字段值
CREATE TABLE u_data_new (
userid INT,
movieid INT,
rating INT,
weekday INT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
//將python文件加載到系統
add FILE weekday_mapper.py;
將數據按周進行分割
INSERT OVERWRITE TABLE u_data_new
SELECT
TRANSFORM (userid, movieid, rating, unixtime)
USING 'python weekday_mapper.py'
AS (userid, movieid, rating, weekday)
FROM u_data; www-463nanren-com
