Hive 是基於Hadoop 構建的一套數據倉庫分析系統,它提供了豐富的SQL查詢方式來分析存儲在Hadoop 分佈式文件系統中的數據,能夠將結構化的數據文件映射爲一張數據庫表,並提供完整的SQL查詢功能,能夠將SQL語句轉換爲MapReduce任務進行運行,經過本身的SQL 去查詢分析須要的內容,這套SQL 簡稱Hive SQL,使不熟悉mapreduce 的用戶很方便的利用SQL 語言查詢,彙總,分析數據。而mapreduce開發人員能夠把己寫的mapper 和reducer 做爲插件來支持Hive 作更復雜的數據分析。
它與關係型數據庫的SQL 略有不一樣,但支持了絕大多數的語句如DDL、DML 以及常見的聚合函數、鏈接查詢、條件查詢。HIVE不適合用於聯機online)事務處理,也不提供實時查詢功能。它最適合應用在基於大量不可變數據的批處理做業。
HIVE的特色:可伸縮(在Hadoop的集羣上動態的添加設備),可擴展,容錯,輸入格式的鬆散耦合。
Hive 的官方文檔中對查詢語言有了很詳細的描述,請參考:http://wiki.apache.org/hadoop/Hive/LanguageManual ,本文的內容大部分翻譯自該頁面,期間加入了一些在使用過程當中須要注意到的事項。
1. DDL 操做
DDL
?建表
?刪除表
?修改表結構
?建立/刪除視圖
?建立數據庫
?顯示命令
建表:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[(col_name data_type [COMMENT col_comment], ...)]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
[CLUSTERED BY (col_name, col_name, ...)
[SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
[ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION hdfs_path]
?CREATE TABLE 建立一個指定名字的表。若是相同名字的表已經存在,則拋出異常;用戶能夠用 IF NOT EXIST 選項來忽略這個異常
?EXTERNAL 關鍵字可讓用戶建立一個外部表,在建表的同時指定一個指向實際數據的路徑(LOCATION)
?LIKE 容許用戶複製現有的表結構,可是不復制數據
?COMMENT能夠爲表與字段增長描述
?ROW FORMAT
DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char]
[MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
| SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
用戶在建表的時候能夠自定義 SerDe 或者使用自帶的 SerDe。若是沒有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,將會使用自帶的 SerDe。在建表的時候,用戶還須要爲表指定列,用戶在指定表的列的同時也會指定自定義的 SerDe,Hive 經過 SerDe 肯定表的具體的列的數據。
?STORED AS
SEQUENCEFILE
| TEXTFILE
| RCFILE
| INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
若是文件數據是純文本,可使用 STORED AS TEXTFILE。若是數據須要壓縮,使用 STORED AS SEQUENCE 。
建立簡單表:
hive> CREATE TABLE pokes (foo INT, bar STRING);
建立外部表:
CREATE EXTERNAL TABLE page_view(viewTime INT, userid BIGINT,
page_url STRING, referrer_url STRING,
ip STRING COMMENT 'IP Address of the User',
country STRING COMMENT 'country of origination')
COMMENT 'This is the staging page view table'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\054'
STORED AS TEXTFILE
LOCATION '<hdfs_location>';
建分區表
CREATE TABLE par_table(viewTime INT, userid BIGINT,
page_url STRING, referrer_url STRING,
ip STRING COMMENT 'IP Address of the User')
COMMENT 'This is the page view table'
PARTITIONED BY(date STRING, pos STRING)
ROW FORMAT DELIMITED ‘\t’
FIELDS TERMINATED BY '\n'
STORED AS SEQUENCEFILE;
建Bucket表
CREATE TABLE par_table(viewTime INT, userid BIGINT,
page_url STRING, referrer_url STRING,
ip STRING COMMENT 'IP Address of the User')
COMMENT 'This is the page view table'
PARTITIONED BY(date STRING, pos STRING)
CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS
ROW FORMAT DELIMITED ‘\t’
FIELDS TERMINATED BY '\n'
STORED AS SEQUENCEFILE;
建立表並建立索引字段ds
hive> CREATE TABLE invites (foo INT, bar STRING) PARTITIONED BY (ds STRING);
複製一個空表
CREATE TABLE empty_key_value_store
LIKE key_value_store;
例子
create table user_info (user_id int, cid string, ckid string, username string)
row format delimited
fields terminated by '\t'
lines terminated by '\n';
導入數據表的數據格式是:字段之間是tab鍵分割,行之間是斷行。
及要咱們的文件內容格式:
100636 100890 c5c86f4cddc15eb7 yyyvybtvt
100612 100865 97cc70d411c18b6f gyvcycy
100078 100087 ecd6026a15ffddf5 qa000100
顯示全部表:
hive> SHOW TABLES;
按正條件(正則表達式)顯示錶,
hive> SHOW TABLES '.*s';
修改表結構
?增長分區、刪除分區
?重命名錶
?修改列的名字、類型、位置、註釋
?增長/更新列
?增長表的元數據信息
表添加一列 :
hive> ALTER TABLE pokes ADD COLUMNS (new_col INT);
添加一列並增長列字段註釋
hive> ALTER TABLE invites ADD COLUMNS (new_col2 INT COMMENT 'a comment');
更改表名:
hive> ALTER TABLE events RENAME TO 3koobecaf;
刪除列:
hive> DROP TABLE pokes;
增長、刪除分區
?增長
ALTER TABLE table_name ADD [IF NOT EXISTS] partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ...
partition_spec:
: PARTITION (partition_col = partition_col_value, partition_col = partiton_col_value, ...)
?刪除
ALTER TABLE table_name DROP partition_spec, partition_spec,...
重命名錶
?ALTER TABLE table_name RENAME TO new_table_name
修改列的名字、類型、位置、註釋:
?ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]
?這個命令能夠容許改變列名、數據類型、註釋、列位置或者它們的任意組合
表添加一列 :
hive> ALTER TABLE pokes ADD COLUMNS (new_col INT);
添加一列並增長列字段註釋
hive> ALTER TABLE invites ADD COLUMNS (new_col2 INT COMMENT 'a comment');node
增長/更新列
?ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...)
? ADD是表明新增一字段,字段位置在全部列後面(partition列前)
REPLACE則是表示替換表中全部字段。
增長表的元數據信息
?ALTER TABLE table_name SET TBLPROPERTIES table_properties table_properties:
:[property_name = property_value…..]
?用戶能夠用這個命令向表中增長metadata
改變表文件格式與組織
?ALTER TABLE table_name SET FILEFORMAT file_format
?ALTER TABLE table_name CLUSTERED BY(userid) SORTED BY(viewTime) INTO num_buckets BUCKETS
?這個命令修改了表的物理存儲屬性
建立/刪除視圖
?CREATE VIEW [IF NOT EXISTS] view_name [ (column_name [COMMENT column_comment], ...) ][COMMENT view_comment][TBLPROPERTIES (property_name = property_value, ...)] AS SELECT
?增長視圖
?若是沒有提供表名,視圖列的名字將由定義的SELECT表達式自動生成
?若是修改基本表的屬性,視圖中不會體現,無效查詢將會失敗
?視圖是隻讀的,不能用LOAD/INSERT/ALTER
?DROP VIEW view_name
?刪除視圖
建立數據庫
?CREATE DATABASE name
顯示命令
?show tables;
?show databases;
?show partitions ;
?show functions
?describe extended table_name dot col_namepython
2. DML 操做:元數據存儲
hive不支持用insert語句一條一條的進行插入操做,也不支持update操做。數據是以load的方式加載到創建好的表中。數據一旦導入就不能夠修改。
DML包括:INSERT插入、UPDATE更新、DELETE刪除
?向數據表內加載文件
?將查詢結果插入到Hive表中
?0.8新特性 insert intomysql
向數據表內加載文件
?LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
?Load 操做只是單純的複製/移動操做,將數據文件移動到 Hive 表對應的位置。
?filepath
?相對路徑,例如:project/data1
?絕對路徑,例如: /user/hive/project/data1
?包含模式的完整 URI,例如:hdfs://namenode:9000/user/hive/project/data1
例如:
hive> LOAD DATA LOCAL INPATH './examples/files/kv1.txt' OVERWRITE INTO TABLE pokes;linux
加載本地數據,同時給定分區信息
?加載的目標能夠是一個表或者分區。若是表包含分區,必須指定每個分區的分區名
?filepath 能夠引用一個文件(這種狀況下,Hive 會將文件移動到表所對應的目錄中)或者是一個目錄(在這種狀況下,Hive 會將目錄中的全部文件移動至表所對應的目錄中)
LOCAL關鍵字
?指定了LOCAL,即本地
?load 命令會去查找本地文件系統中的 filepath。若是發現是相對路徑,則路徑會被解釋爲相對於當前用戶的當前路徑。用戶也能夠爲本地文件指定一個完整的 URI,好比:file:///user/hive/project/data1.
?load 命令會將 filepath 中的文件複製到目標文件系統中。目標文件系統由表的位置屬性決定。被複制的數據文件移動到表的數據對應的位置web
例如:加載本地數據,同時給定分區信息:
hive> LOAD DATA LOCAL INPATH './examples/files/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15');正則表達式
? 沒有指定LOCAL
若是 filepath 指向的是一個完整的 URI,hive 會直接使用這個 URI。 不然
?若是沒有指定 schema 或者 authority,Hive 會使用在 hadoop 配置文件中定義的 schema 和 authority,fs.default.name 指定了 Namenode 的 URI
?若是路徑不是絕對的,Hive 相對於 /user/ 進行解釋。 Hive 會將 filepath 中指定的文件內容移動到 table (或者 partition)所指定的路徑中
加載DFS數據 ,同時給定分區信息:
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.sql
OVERWRITE
?指定了OVERWRITE
?目標表(或者分區)中的內容(若是有)會被刪除,而後再將 filepath 指向的文件/目錄中的內容添加到表/分區中。
?若是目標表(分區)已經有一個文件,而且文件名和 filepath 中的文件名衝突,那麼現有的文件會被新文件所替代。
將查詢結果插入Hive表
?將查詢結果插入Hive表
?將查詢結果寫入HDFS文件系統
?基本模式
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement
?多插入模式
FROM from_statement
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1
[INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2] ...
?自動分區模式
INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement
將查詢結果寫入HDFS文件系統
?INSERT OVERWRITE [LOCAL] DIRECTORY directory1 SELECT ... FROM ...
FROM from_statement
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 select_statement1
[INSERT OVERWRITE [LOCAL] DIRECTORY directory2 select_statement2]
?
?數據寫入文件系統時進行文本序列化,且每列用^A 來區分,\n換行
INSERT INTO
?INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement數據庫
3. DQL 操做:數據查詢SQL
SQL操做
?基本的Select 操做
?基於Partition的查詢
?Joinexpress
3.1 基本的Select 操做
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list [HAVING condition]]
[ CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list]
]
[LIMIT number]
?使用ALL和DISTINCT選項區分對重複記錄的處理。默認是ALL,表示查詢全部記錄。DISTINCT表示去掉重複的記錄
?
?Where 條件
?相似咱們傳統SQL的where 條件
?目前支持 AND,OR ,0.9版本支持between
?IN, NOT IN
?不支持EXIST ,NOT EXIST
ORDER BY與SORT BY的不一樣
?ORDER BY 全局排序,只有一個Reduce任務
?SORT BY 只在本機作排序
Limit
?Limit 能夠限制查詢的記錄數
SELECT * FROM t1 LIMIT 5
?實現Top k 查詢
?下面的查詢語句查詢銷售記錄最大的 5 個銷售表明。
SET mapred.reduce.tasks = 1
SELECT * FROM test SORT BY amount DESC LIMIT 5
?REGEX Column Specification
SELECT 語句可使用正則表達式作列選擇,下面的語句查詢除了 ds 和 hr 以外的全部列:
SELECT `(ds|hr)?+.+` FROM testapache
例如
按先件查詢
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;
將文件流直接插入文件:
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)
3.2 基於Partition的查詢
?通常 SELECT 查詢會掃描整個表,使用 PARTITIONED BY 子句建表,查詢就能夠利用分區剪枝(input pruning)的特性
?Hive 當前的實現是,只有分區斷言出如今離 FROM 子句最近的那個WHERE 子句中,纔會啓用分區剪枝
3.3 Join
Syntax
join_table:
table_reference JOIN table_factor [join_condition]
| table_reference {LEFT|RIGHT|FULL} [OUTER] JOIN table_reference join_condition
| table_reference LEFT SEMI JOIN table_reference join_condition
table_reference:
table_factor
| join_table
table_factor:
tbl_name [alias]
| table_subquery alias
| ( table_references )
join_condition:
ON equality_expression ( AND equality_expression )*
equality_expression:
expression = expression
?Hive 只支持等值鏈接(equality joins)、外鏈接(outer joins)和(left semi joins)。Hive 不支持全部非等值的鏈接,由於非等值鏈接很是難轉化到 map/reduce 任務
?LEFT,RIGHT和FULL OUTER關鍵字用於處理join中空記錄的狀況
?LEFT SEMI JOIN 是 IN/EXISTS 子查詢的一種更高效的實現
?join 時,每次 map/reduce 任務的邏輯是這樣的:reducer 會緩存 join 序列中除了最後一個表的全部表的記錄,再經過最後一個表將結果序列化到文件系統
?實踐中,應該把最大的那個表寫在最後
join 查詢時,須要注意幾個關鍵點
?只支持等值join
?SELECT a.* FROM a JOIN b ON (a.id = b.id)
?SELECT a.* FROM a JOIN b
ON (a.id = b.id AND a.department = b.department)
?能夠 join 多於 2 個表,例如
SELECT a.val, b.val, c.val FROM a JOIN b
ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
?若是join中多個表的 join key 是同一個,則 join 會被轉化爲單個 map/reduce 任務
LEFT,RIGHT和FULL OUTER
?例子
?SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key)
?若是你想限制 join 的輸出,應該在 WHERE 子句中寫過濾條件——或是在 join 子句中寫
?
?容易混淆的問題是表分區的狀況
? SELECT c.val, d.val FROM c LEFT OUTER JOIN d ON (c.key=d.key)
WHERE a.ds='2010-07-07' AND b.ds='2010-07-07‘
?若是 d 表中找不到對應 c 表的記錄,d 表的全部列都會列出 NULL,包括 ds 列。也就是說,join 會過濾 d 表中不能找到匹配 c 表 join key 的全部記錄。這樣的話,LEFT OUTER 就使得查詢結果與 WHERE 子句無關
?解決辦法
?SELECT c.val, d.val FROM c LEFT OUTER JOIN d
ON (c.key=d.key AND d.ds='2009-07-07' AND c.ds='2009-07-07')
LEFT SEMI JOIN
?LEFT SEMI JOIN 的限制是, JOIN 子句中右邊的表只能在 ON 子句中設置過濾條件,在 WHERE 子句、SELECT 子句或其餘地方過濾都不行
?
?SELECT a.key, a.value
FROM a
WHERE a.key in
(SELECT b.key
FROM B);
能夠被重寫爲:
SELECT a.key, a.val
FROM a LEFT SEMI JOIN b on (a.key = b.key)
UNION ALL
?用來合併多個select的查詢結果,須要保證select中字段須一致
?select_statement UNION ALL select_statement UNION ALL select_statement ...
4. 從SQL到HiveQL應轉變的習慣
一、Hive不支持等值鏈接
?SQL中對兩表內聯能夠寫成:
?select * from dual a,dual b where a.key = b.key;
?Hive中應爲
?select * from dual a join dual b on a.key = b.key;
而不是傳統的格式:
SELECT t1.a1 as c1, t2.b1 as c2FROM t1, t2 WHERE t1.a2 = t2.b2
二、分號字符
?分號是SQL語句結束標記,在HiveQL中也是,可是在HiveQL中,對分號的識別沒有那麼智慧,例如:
?select concat(key,concat(';',key)) from dual;
?但HiveQL在解析語句時提示:
FAILED: Parse Error: line 0:-1 mismatched input '' expecting ) in function specification
?解決的辦法是,使用分號的八進制的ASCII碼進行轉義,那麼上述語句應寫成:
?select concat(key,concat('\073',key)) from dual;
三、IS [NOT] NULL
?SQL中null表明空值, 值得警戒的是, 在HiveQL中String類型的字段如果空(empty)字符串, 即長度爲0, 那麼對它進行IS NULL的判斷結果是False.
四、Hive不支持將數據插入現有的表或分區中,
僅支持覆蓋重寫整個表,示例以下:
[sql] view plaincopyprint?
1. INSERT OVERWRITE TABLE t1
2. SELECT * FROM t2;
四、hive不支持INSERT INTO, UPDATE, DELETE操做
這樣的話,就不要很複雜的鎖機制來讀寫數據。
INSERT INTO syntax is only available starting in version 0.8。INSERT INTO就是在表或分區中追加數據。
五、hive支持嵌入mapreduce程序,來處理複雜的邏輯
如:
[sql] view plaincopyprint?
1. FROM (
2. MAP doctext USING 'python wc_mapper.py' AS (word, cnt)
3. FROM docs
4. CLUSTER BY word
5. ) a
6. REDUCE word, cnt USING 'python wc_reduce.py';
--doctext: 是輸入
--word, cnt: 是map程序的輸出
--CLUSTER BY: 將wordhash後,又做爲reduce程序的輸入
而且map程序、reduce程序能夠單獨使用,如:
[sql] view plaincopyprint?
1. FROM (
2. FROM session_table
3. SELECT sessionid, tstamp, data
4. DISTRIBUTE BY sessionid SORT BY tstamp
5. ) a
6. REDUCE sessionid, tstamp, data USING 'session_reducer.sh';
--DISTRIBUTE BY: 用於給reduce程序分配行數據
六、hive支持將轉換後的數據直接寫入不一樣的表,還能寫入分區、hdfs和本地目錄。
這樣能免除屢次掃描輸入表的開銷。
[sql] view plaincopyprint?
1. FROM t1
2.
3. INSERT OVERWRITE TABLE t2
4. SELECT t3.c2, count(1)
5. FROM t3
6. WHERE t3.c1 <= 20
7. GROUP BY t3.c2
8.
9. INSERT OVERWRITE DIRECTORY '/output_dir'
10. SELECT t3.c2, avg(t3.c1)
11. FROM t3
12. WHERE t3.c1 > 20 AND t3.c1 <= 30
13. GROUP BY t3.c2
14.
15. INSERT OVERWRITE LOCAL DIRECTORY '/home/dir'
16. SELECT t3.c2, sum(t3.c1)
17. FROM t3
18. WHERE t3.c1 > 30
19. GROUP BY t3.c2;
5. 實際示例
建立一個表
CREATE TABLE u_data (
userid INT,
movieid INT,
rating INT,
unixtime STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '/t'
STORED AS TEXTFILE;
下載示例數據文件,並解壓縮
wget http://www.grouplens.org/system/files/ml-data.tar__0.gz
tar xvzf ml-data.tar__0.gz
加載數據到表中:
LOAD DATA LOCAL INPATH 'ml-data/u.data'
OVERWRITE INTO TABLE u_data;
統計數據總量:
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;
SELECT weekday, COUNT(1)
FROM u_data_new
GROUP BY weekday;
處理Apache Weblog 數據
將WEB日誌先用正則表達式進行組合,再按須要的條件進行組合輸入到表中
add jar ../build/contrib/hive_contrib.jar;
CREATE TABLE apachelog (
host STRING,
identity STRING,
user STRING,
time STRING,
request STRING,
status STRING,
size STRING,
referer STRING,
agent STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) (-|//[[^//]]*//]) ([^ /"]*|/"[^/"]*/") (-|[0-9]*) (-|[0-9]*)(?: ([^ /"]*|/"[^/"]*/") ([^ /"]*|/"[^/"]*/"))?",
"output.format.string" = "%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s"
)
STORED AS TEXTFILE;
Hive經常使用的SQL命令操做
(2012-09-20 17:30:04)
轉載▼
標籤:
雜談
分類: Internet和計算機
Hive提供了不少的函數,能夠在命令行下show functions羅列全部的函數,你會發現這些函數名與mysql的很相近,絕大多數相同的,可經過describe function functionName 查看函數使用方法。
hive支持的數據類型很簡單就INT(4 byte integer),BIGINT(8 byte integer),FLOAT(single precision),DOUBLE(double precision),BOOLEAN,STRING等原子類型,連日期時間類型也不支持,但經過to_date、unix_timestamp、date_diff、date_add、date_sub等函數就能完成mysql一樣的時間日期複雜操做。
以下示例:
select * from tablename where to_date(cz_time) > to_date('2050-12-31');
select * from tablename where unix_timestamp(cz_time) > unix_timestamp('2050-12-31 15:32:28');
分區
hive與mysql分區有些區別,mysql分區是用表結構中的字段來分區(range,list,hash等),而hive不一樣,他須要手工指定分區列,這個列是獨立於表結構,但屬於表中一列,在加載數據時手動指定分區。
建立表
hive> CREATE TABLE pokes (foo INT, bar STRING COMMENT 'This is bar');
建立表並建立索引字段ds
hive> CREATE TABLE invites (foo INT, bar STRING) PARTITIONED BY (ds STRING);
顯示全部表
hive> SHOW TABLES;
按正條件(正則表達式)顯示錶,
hive> SHOW TABLES '.*s';
表添加一列
hive> ALTER TABLE pokes ADD COLUMNS (new_col INT);
添加一列並增長列字段註釋
hive> ALTER TABLE invites ADD COLUMNS (new_col2 INT COMMENT 'a comment');
更改表名
hive> ALTER TABLE events RENAME TO 3koobecaf;
刪除列
hive> DROP TABLE pokes;
元數據存儲
將本地文件中的數據加載到表中
hive> LOAD DATA LOCAL INPATH './examples/files/kv1.txt' OVERWRITE INTO TABLE pokes;
加載本地數據,同時給定分區信息
hive> LOAD DATA LOCAL INPATH './examples/files/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15');
加載DFS數據 ,同時給定分區信息
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.
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;
將文件流直接插入文件
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)
實際示例
建立一個表
CREATE TABLE u_data (
userid INT,
movieid INT,
rating INT,
unixtime STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE;
下載示例數據文件,並解壓縮
wget http://www.grouplens.org/system/files/ml-data.tar__0.gz
tar xvzf ml-data.tar__0.gz
加載數據到表中
LOAD DATA LOCAL INPATH 'ml-data/u.data'
OVERWRITE INTO TABLE u_data;
統計數據總量
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;
SELECT weekday, COUNT(1)
FROM u_data_new
GROUP BY weekday;
(轉)hive sql 學習筆記(1)
1、 建立表
在官方的wiki裏,example是這樣的:
1. CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
2. [(col_name data_type [COMMENT col_comment], ...)]
3. [COMMENT table_comment]
4. [PARTITIONED BY (col_name data_type
5. [COMMENT col_comment], ...)]
6. [CLUSTERED BY (col_name, col_name, ...)
7. [SORTED BY (col_name [ASC|DESC], ...)]
8. INTO num_buckets BUCKETS]
9. [ROW FORMAT row_format]
10. [STORED AS file_format]
11. [LOCATION hdfs_path]
row_format
: DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char]
[MAP KEYS TERMINATED BY char]
| SERDE serde_name [WITH SERDEPROPERTIES property_name=property_value,
property_name=property_value, ...]
file_format:
: SEQUENCEFILE
| TEXTFILE
| INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
[ROW FORMAT DELIMITED]關鍵字,是用來設置建立的表在加載數據的時候,支持的列分隔符;
[STORED AS file_format]關鍵字是用來設置加載數據的數據類型。Hive自己支持的文件格式只有:Text File,Sequence File。若是文件數據是純文本,可使用 [STORED AS TEXTFILE]。若是數據須要壓縮,使用 [STORED AS SEQUENCE] 。一般狀況,只要不須要保存序列化的對象,咱們默認採用[STORED AS TEXTFILE]。
那麼咱們建立一張普通的hive表,hive sql就以下:
1. CREATE TABLE test_1(id INT, name STRING, city STRING) SORTED BY TEXTFILE ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’ ;
其中,hive支持的字段類型,並很少,能夠簡單的理解爲數字類型和字符串類型,詳細列表以下:
1. TINYINT
2. SMALLINT
3. INT
4. BIGINT
5. BOOLEAN
6. FLOAT
7. DOUBLE
8. STRING
注意partitioned by 的位置:
create table webdata2(vstart string,vend string,hdid int,userid int,sid int,refsid int,active int,duration int,mdomain string,sdomain string,refsdomain string,ieid int,refieid string,url string,totaltime int,param2 int,param4 string,param4code string) partitioned by(pid int,daytime string) row format delimited fields terminated by '\t' stored as SEQUENCEFILE;
Hive的表,與普通關係型數據庫,如mysql在表上有很大的區別,全部hive的表都是一個文件,它是基於Hadoop的文件系統來作的。
hive整體來講能夠總結爲三種不一樣類型的表。
1. 普通表
普通表的建立,如上所說,不講了。其中,一個表,就對應一個表名對應的文件。
2. 外部表
EXTERNAL 關鍵字可讓用戶建立一個外部表,在建表的同時指定一個指向實際數據的路徑(LOCATION),Hive 建立內部表時,會將數據移動到數據倉庫指向的路徑;若建立外部表,僅記錄數據所在的路徑,不對數據的位置作任何改變。在刪除表的時候,內部表的元數據和數據會被一塊兒刪除,而外部表只刪除元數據,不刪除數據。具體sql以下:
1. CREATE EXTERNAL TABLE test_1(id INT, name STRING, city STRING) SORTED BY TEXTFILE ROW FORMAT DELIMITED FIELDS TERMINATED BY'\t’ LOCATION ‘hdfs://http://www.cnblogs.com/..’
3. 分區表
有分區的表能夠在建立的時候使用 PARTITIONED BY 語句。一個表能夠擁有一個或者多個分區,每個分區單獨存在一個目錄下。並且,表和分區均可以對某個列進行 CLUSTERED BY 操做,將若干個列放入一個桶(bucket)中。也能夠利用SORT BY 對數據進行排序。這樣能夠爲特定應用提升性能。具體SQL以下:
1. CREATE TABLE test_1(id INT, name STRING, city STRING) PARTITIONED BY (pt STRING) SORTED BY TEXTFILE ROW FORMAT DELIMITED FIELDS TERMINATED BY‘\t’
Hive的排序,由於底層實現的關係,比較不一樣於普通排序,這裏先不講。
桶的概念,主要是爲性能考慮,能夠理解爲對分區內列,進行再次劃分,提升性能。在底層,一個桶實際上是一個文件。若是桶劃分過多,會致使文件數量暴增,一旦達到系統文件數量的上限,就杯具了。哪一種是最優數量,這個哥也不知道。
分區表實際是一個文件夾,表名即文件夾名。每一個分區,實際是表名這個文件夾下面的不一樣文件。分區能夠根據時間、地點等等進行劃分。好比,天天一個分區,等於天天存天天的數據;或者每一個城市,存放每一個城市的數據。每次查詢數據的時候,只要寫下相似 where pt=2010_08_23這樣的條件便可查詢指定時間得數據。
整體而言,普通表,相似mysql的表結構,外部表的意義更可能是指數據的路徑映射。分區表,是最難以理解,也是最hive最大的優點。以後會專門針對分區表進行講解。
2、 加載數據
Hive不支持一條一條的用insert語句進行插入操做,也不支持update的操做。數據是以load的方式,加載到創建好的表中。數據一旦導入,則不可修改。要麼drop掉整個表,要麼創建新的表,導入新的數據。
官方指導爲:
1. LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
Hive在數據load這塊,大方向分爲兩種方式,load文件或者查詢一張表,或者將某張表裏的額查詢結果插入指定表。
若是劃分更細一點我的概括總結爲4種不一樣的方式的load:
1. Load data到指定的表
直接將file,加載到指定的表,其中,表能夠是普通表或者分區表。具體sql以下:
1. LOAD DATA LOCAL INPATH '/home/admin/test/test.txt' OVERWRITE INTO TABLE test_1
關鍵字[OVERWRITE]意思是是覆蓋原表裏的數據,不寫則不會覆蓋。
關鍵字[LOCAL]是指你加載文件的來源爲本地文件,不寫則爲hdfs的文件。
其中
‘/home/admin/test/test.txt’爲絕對路徑
2. load到指定表的分區
直接將file,加載到指定表的指定分區。表自己必須是分區表,若是是普通表,導入會成功,可是數據實際不會被導入。具體sql以下:
1. LOAD DATA LOCAL INPATH '/home/admin/test/test.txt' OVERWRITE INTO TABLE test_1 PARTITION(pt=’xxxx)
load數據,hive支持文件夾的方式,將文件夾內的全部文件,都load到指定表中。Hdfs會將文件系統內的某文件夾路徑內的文件,分散到不一樣的實際物理地址中。這樣,在數據量很大的時候,hive支持讀取多個文件載入,而不須要限定在惟一的文件中。
3. insert+select
這個是徹底不一樣於文件操做的數據導入方式。官方指導爲:
1. Standard syntax:
2. INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement
3.
4. Hive extension (multiple inserts):
5. FROM from_statement
6. INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1
7. [INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2] ...
8.
9. Hive extension (dynamic partition inserts):
10. INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement
這個的用法,和上面兩種直接操做file的方式,大相徑庭。從sql語句自己理解,就是把查詢到的數據,直接導入另一張表。這個暫時不仔細分析,以後查詢章節,再細講。
4. alter 表,對分區操做
在對錶結構進行修改的時候,咱們能夠增長一個新的分區,在增長新分區的同時,將數據直接load到新的分區當中。
1. ALTER TABLE table_name ADD
2. partition_spec [ LOCATION 'location1' ]
3. partition_spec [ LOCATION 'location2' ] ...
Hadoop Hive SQL語法詳解
[日期:2012-02-14] 來源:Linux社區 做者:hguisu [字體:大 中 小]
DDL Operations
建立表:
hive> CREATE TABLE pokes (foo INT, bar STRING);
建立表並建立索引字段ds
hive> CREATE TABLE invites (foo INT, bar STRING) PARTITIONED BY (ds STRING);
顯示全部表:
hive> SHOW TABLES;
按正條件(正則表達式)顯示錶,
hive> SHOW TABLES '.*s';
表添加一列 :
hive> ALTER TABLE pokes ADD COLUMNS (new_col INT);
添加一列並增長列字段註釋
hive> ALTER TABLE invites ADD COLUMNS (new_col2 INT COMMENT 'a comment');
更改表名:
hive> ALTER TABLE events RENAME TO 3koobecaf;
刪除列:
hive> DROP TABLE pokes;
元數據存儲:
將文件中的數據加載到表中
hive> LOAD DATA LOCAL INPATH './examples/files/kv1.txt' OVERWRITE INTO TABLE pokes;
加載本地數據,同時給定分區信息
hive> LOAD DATA LOCAL INPATH './examples/files/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15');
加載DFS數據 ,同時給定分區信息
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.
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;
將文件流直接插入文件:
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)
實際示例:
建立一個表
CREATE TABLE u_data (
userid INT,
movieid INT,
rating INT,
unixtime STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '/t'
STORED AS TEXTFILE;
下載示例數據文件,並解壓縮
wget http://www.grouplens.org/system/files/ml-data.tar__0.gz
tar xvzf ml-data.tar__0.gz
加載數據到表中:
LOAD DATA LOCAL INPATH 'ml-data/u.data'
OVERWRITE INTO TABLE u_data;
統計數據總量:
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;
SELECT weekday, COUNT(1)
FROM u_data_new
GROUP BY weekday;
處理Apache Weblog 數據
將WEB日誌先用正則表達式進行組合,再按須要的條件進行組合輸入到表中
add jar ../build/contrib/hive_contrib.jar;
CREATE TABLE apachelog (
host STRING,
identity STRING,
user STRING,
time STRING,
request STRING,
status STRING,
size STRING,
referer STRING,
agent STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) (-|//[[^//]]*//]) ([^ /"]*|/"[^/"]*/") (-|[0-9]*) (-|[0-9]*)(?: ([^ /"]*|/"[^/"]*/") ([^ /"]*|/"[^/"]*/"))?",
"output.format.string" = "%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s"
)
STORED AS TEXTFILE;
本篇文章來源於 Linux公社網站(www.linuxidc.com) 原文連接:http://www.linuxidc.com/Linux/2012-02/54226.htm
Hive經常使用的SQL命令操做
分類: Hive 2013-12-07 12:35 1102人閱讀 評論(0) 收藏 舉報
建立表
hive> CREATE TABLE pokes (foo INT, bar STRING);
建立表並建立索引字段ds
hive> CREATE TABLE invites (foo INT, bar STRING) PARTITIONED BY (ds STRING);
顯示全部表
hive> SHOW TABLES;
按正條件(正則表達式)顯示錶,
hive> SHOW TABLES '.*s';
表添加一列
hive> ALTER TABLE pokes ADD COLUMNS (new_col INT);
添加一列並增長列字段註釋
hive> ALTER TABLE invites ADD COLUMNS (new_col2 INT COMMENT 'a comment');
更改表名
hive> ALTER TABLE events RENAME TO 3koobecaf;
刪除列
hive> DROP TABLE pokes;
元數據存儲
將文件中的數據加載到表中
hive> LOAD DATA LOCAL INPATH './examples/files/kv1.txt' OVERWRITE INTO TABLE pokes;
加載本地數據,同時給定分區信息
hive> LOAD DATA LOCAL INPATH './examples/files/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15');
加載DFS數據 ,同時給定分區信息
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.
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;
將文件流直接插入文件
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)
實際示例
建立一個表
CREATE TABLE u_data (
userid INT,
movieid INT,
rating INT,
unixtime STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE;
下載示例數據文件,並解壓縮
wget http://www.grouplens.org/system/files/ml-data.tar__0.gz
tar xvzf ml-data.tar__0.gz
加載數據到表中
LOAD DATA LOCAL INPATH 'ml-data/u.data'
OVERWRITE INTO TABLE u_data;
統計數據總量
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;
SELECT weekday, COUNT(1)
FROM u_data_new
GROUP BY weekday;
————————————————————————————————————————————————————
hive update delete:
關於 hive 的更新和刪除問題,csdn 曾舉辦過活動來專門討論過,
http://10773851.42qu.com/10773869
總結以下:
HIVE是一個數據倉庫系統,這就意味着它能夠不支持普通數據庫的CRUD操做。CRUD應該在導入HIVE數據倉庫前完成。
並且鑑於 hdfs 的特色,其並不能高效的支持流式訪問,訪問都是以遍歷整個文件塊的方式。hive 0.7 以後已經支持
索引,可是很弱,尚沒有成熟的線上方案。
關於 hive 的刪除和更新有以下辦法:
1、行級的更新和刪除:經過 hbase 進行。
數據保存在HBase中,Hive從HBase中查詢數據,這個官方提供 hive-hbase-handler 插件支持,經過 thrift hive-service 進行通訊
優勢:
適用性比較廣泛,單行和批量修改均可以使用,而且修改也比較方便;修改也比較快速。
缺點:
(1)查詢的時候,性能較數據保存在HDFS的場景慢一些。
(2)經過 hbase 刪除可能會有延時致使髒數據,由於 habse 刪數據是先邏輯刪除,而後等待下一次 compact 再物理刪除。
(3)這種方式產生的 hive 表將不能再更改表結構,alt table 操做直接拋異常。
(4)尚沒有驗證這種方案在大數據量的場景下的可行性。
2、批量更新和刪除:能夠相應的使用 insert as select 的方式來實現。
不更改HIVE的設計,利用HiveQL實現update和delete,雖然效率比較低,可是也能夠實現update和delete操做。
delete操做實現:
用select語句篩選出不delete的數據,用這些數據覆蓋原來的表,如咱們想刪除score在60分如下的行,能夠用:
INSERT OVERWRITE students SELECT students.* from students where score >= 60;
update操做的實現:
將要更新的數據從數據庫中選出放入一個本地臨時的文件中,如要更新60分如下的學生的數據,可使用:
INSERT OVERRITE LOCAL DIRECTORY "/tmp/students.1" SELECT students.* from students where score < 60;
刪除要更新的數據:
INSERT OVERWRITE students SELECT students.* from students where score >=60;
編輯要更新的數據文件或者將要修改的數據放入數據庫表後再修改,修改結束後載入到表中:LOAD DATA INPATH "/tmp/students.1" INTO TABLE students若是對錶進行分區,上述的update和delete速度會快一些。
缺點:同一個操做掃描了 2 遍 hdfs,還不如 MR 批量更新來得快和簡潔。