Hive的基本理論與安裝可參看做者上一篇博文《Apache Hive 基本理論與安裝指南》。html
全部的hive命令均可以經過hive命令行去執行,hive命令行中仍有許多選項。使用$hive -H查看:java
-e 選項後面能夠直接接一個hql語句,不用進入到hive命令行用戶接口再輸入hql語句。sql
-f 選項後面接一個hql語句的文件。shell
-i 選項在hql語句執行以前的初始化hql文件。例如添加、導入等操做均可以寫在這個hql語句文件中。數據庫
在hive使用中,大可能是寫不少腳本,在hive命令行中輸入是屬於交互式的,這就必須有工做人員在工做,不適合作批量處理。可使用-f或-i選項,一次性執行能夠將全部的hql語句放在一個hql腳本文件中。例如:apache
$ mkdir -p /opt/shell/sql $ vim /opt/shell/sql/test.sql
select * from table_name limit 5; select * from table_name where professional="student"; select count(*) from table_name; select count(*) from table_name group by professional; select * from table_name where professional="student" order by age;
將腳本保存退出後,再批量執行:json
$ hive -f /opt/shell/sql/test.sql
詳見官方文檔。重點在於建立表和建立函數。vim
從官方文檔的Create Table中能夠查看hive建表的命令,以下:數組
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- (Note: TEMPORARY available in Hive 0.14.0 and later) [(col_name data_type [COMMENT col_comment], ... [constraint_specification])] [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] [SKEWED BY (col_name, col_name, ...) -- (Note: Available in Hive 0.10.0 and later)] ON ((col_value, col_value, ...), (col_value, col_value, ...), ...) [STORED AS DIRECTORIES] [ [ROW FORMAT row_format] [STORED AS file_format] | STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)] -- (Note: Available in Hive 0.6.0 and later) ] [LOCATION hdfs_path] [TBLPROPERTIES (property_name=property_value, ...)] -- (Note: Available in Hive 0.6.0 and later) [AS select_statement]; -- (Note: Available in Hive 0.5.0 and later; not supported for external tables) CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name LIKE existing_table_or_view_name [LOCATION hdfs_path];
data_type : primitive_type | array_type | map_type | struct_type | union_type -- (Note: Available in Hive 0.7.0 and later)
data_type,有兩種類型:一種是複雜類型,例如array_type(ARRAY < data_type >)、map_type(MAP < primitive_type, data_type >)、struct_type(STRUCT < col_name : data_type [COMMENT col_comment], ...>)、union_type(UNIONTYPE < data_type, data_type, ... >);簡單類型有SMALLINT(佔2個字節的整數)、INT(佔4個字節的整數)、BIGINT(佔8個字節的整數)、BOOLEAN、FLOAT、DOUBLE、STRING、BINARY、TIMESTAMP、DECIMAL、DATE、VARCHAR(0.12以後)、CHAR(字符,0.13以後)。瀏覽器
primitive_type : TINYINT | SMALLINT | INT | BIGINT | BOOLEAN | FLOAT | DOUBLE | DOUBLE PRECISION -- (Note: Available in Hive 2.2.0 and later) | STRING | BINARY -- (Note: Available in Hive 0.8.0 and later) | TIMESTAMP -- (Note: Available in Hive 0.8.0 and later) | DECIMAL -- (Note: Available in Hive 0.11.0 and later) | DECIMAL(precision, scale) -- (Note: Available in Hive 0.13.0 and later) | DATE -- (Note: Available in Hive 0.12.0 and later) | VARCHAR -- (Note: Available in Hive 0.12.0 and later) | CHAR -- (Note: Available in Hive 0.13.0 and later)
row_format : DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS TERMINATED BY char] [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char] [NULL DEFINED AS char] -- (Note: Available in Hive 0.13 and later) | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
row_format:須要指出每一行是由什麼隔開,而且要指出每一行中的每個字段是用什麼隔開的。
對於字段的隔開,複雜數據類型和簡單數據類型不同。例如數組類型是複雜類型,其隔開符[COLLECTION ITEMS TERMINATED BY char],Map類型的要使用[MAP KEYS TERMINATED BY char]。[LINES TERMINATED BY char]能夠設置行隔開符,若是不寫,默認爲回車換行。
file_format: : SEQUENCEFILE | TEXTFILE -- (Default, depending on hive.default.fileformat configuration) | RCFILE -- (Note: Available in Hive 0.6.0 and later) | ORC -- (Note: Available in Hive 0.11.0 and later) | PARQUET -- (Note: Available in Hive 0.13.0 and later) | AVRO -- (Note: Available in Hive 0.14.0 and later) | INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
SEQUENCEFILE表示序列壓縮格式,以及RCFILE、ORC、PARQUET、AVRO都是壓縮格式。TEXTFILE是默認的格式,文本格式。
爲舉例說明,這裏先生成數據文件:
vim /root/person.txt
1,zhangsan,31,books-sports-math,city:shanghai-street:lujiazui-zipcode:313100 2,lisi,35,books-music,city:hangzhou-street:xihu-zipcode:222100 3,wangwu,25,computer-games,city:guangzhou-street:baiyun-zipcode:212300
根據數據建立一我的類表,包含人的編號、姓名、年齡、愛好、地址五個字段。
vim /opt/shell/sql/t_person.sql
create table t_person ( id int, name string, age int, likes array<string>, address map<string,string> ) row format delimited fields terminated by ',' collection items terminated by '-' map keys terminated by ':' lines terminated by '\n' stored as textfile;
根據表結構,字段之間按,隔開;likes的類型是array,因此能夠有多個愛好,元素之間按-隔開,以,做爲數組的結束;地址是map類型,也是collection類型, key和value按:隔開,每對key和value之間用-隔開(和collection一致);回車表明換行符。
執行建立表腳本:
$ hive -f /opt/shell/sql/t_person.sql
hive> load data local inpath '/root/person.txt' into table t_person;
當咱們要在關係型數據庫中查找某一數據時,通常須要匹配數據庫中的全部數據,因此能夠經過分區來提升查詢效率。把經常使用的查詢條件做爲一種分區,例如要查某一天的數據,事實上就是能夠只匹配當天的數據,其餘數據不匹配。下面以建一個日誌管理表爲例:
文件常常按照天、小時等進行分割。故在此建立多個文件以下:
vim /root/log_2016-03-11.txt
111,1,200,2016-03-11 135,4,100,2016-03-11 211,3,300,2016-03-11 141,1,200,2016-03-11 131,2,400,2016-03-11
vim /root/log_2016-03-12.txt
121,2,300,2016-03-12 125,3,400,2016-03-12 211,1,400,2016-03-12 161,3,100,2016-03-12 171,5,200,2016-03-12
create table t_log (id string,type int,pid string,logtime string) partitioned by (day string) row format delimited fields terminated by ',' stored as textfile;
這裏指定了按照天作分區。
hive> load data local inpath '/root/log_2016-03-11.txt' into table t_log partition (day='2016-03-11'); hive> load data local inpath '/root/log_2016-03-12.txt' into table t_log partition (day='2016-03-12');
hive> select * from t_log;
從上圖能夠看出,數據增長了一個字段,左邊是logtime,右邊是分區day。因此,添加一個分區能夠理解爲添加一個字段;可是又不一樣於添加一個字段,由於查詢按照分區作限定(查詢分區day='2016-03-11')時其餘分區的數據不讀取,而若是是字段的話,須要每一條數據進行匹配過濾。也能夠從瀏覽器看出建立分區表的目錄結構以下:
建立分區,就會爲每個分區建一個目錄,因此在查詢時,只在限定的分區目錄裏查詢。
查看某一天的數據量
hive> select count(*) from t_log where day='2016-03-11';
查看某一個月的數據量
hive>select count(*) from t_log where day between 'xxx' and 'xxx';
固然,這裏須要先轉換格式,略。
詳見官方文檔。DML是對數據進行增刪改的腳本。可是數據在hdfs中,實際上不提供修改,只提供追加(insert),支持刪除。
load file將數據導入到表中。其語法爲:
hive> LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
local:若是導入的數據在Linux主機本地,就要添加[local],若是數據已經在hdfs上就不能加local;overwrite:覆蓋;partition:若是表有分區就要加partition。
首先,上傳Linux文件到hdfs
$ hdfs dfs -put /root/log_2016-03-1* /usr/input
其次,在hive中執行導入
hive>load data inpath '/usr/input/log_2016-03-12.txt' into table t_log partition (day='2016-03-12');
hive>load data inpath '/usr/input/log_2016-03-12.txt' overwrite into table t_log partition (day='2016-03-12');
注意:導入的分區要存在,導入到hive表後原來hdfs路徑下的文件就不復存在了,即存在hdfs的目錄變了,實際就是元數據變了,block的位置沒有變。若是使用overwrite,則原來該表中指定分區的數據將所有清空,而後上傳該文件。若是load相同文件名名到表中時,會默認生成副本filename_copy_1。文件中的數據格式要和表的結構相吻合。
hive>load data local inpath '/root/log_2016-03-11.txt' into table t_log partition (day='2016-03-11');
hive> INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement;
hive> INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
其中的select_statement1 FROM from_statement;是一個sql語句。這是用於查詢hive中已經存在的數據,將查詢結果給到一張新表中。
hive> INSERT INTO TABLE tablename [PARTITION (partcol1[=val1], partcol2[=val2] ...)] VALUES values_row [, values_row ...]
這個語句是和關係型數據庫的insert語句用法是同樣的。區別有三:一是,有partition;二是,能夠一次插入多條數據;三是,這種語句是轉成MapReduce去執行的。
由於hive是一個工具,其做用是查詢和統計hdfs上的數據的,對於查詢結果通常就在控制檯上顯示,因此這個insert語句做用就是將查詢的結果保存下來,用於後期的展現。
hive> insert into table t_log partition (day='2016-03-13’) values ('888',2,'100','2016-03-13’);
這個會啓動MapReduce,由於數據在文件中不存在,要插到文件中至關於上傳,會生成一個新的文件。這個不經常使用。因此實際上inset into語句的實際意義在於將查詢結果放到新的表中。
刪除數據通常能夠不在hive中刪除,直接在hdfs上刪除文件。由於刪數據實際上就是刪除文件。例如要刪除以前插入到hive的t_log表day=2016-03-11分區下的log_2016-03-11.txt,能夠執行以下命令:
#hdfs dfs -rm /user/hive/warehouse/t_log/day=2016-03-11/t_log-2016-03-11.txt
詳見官方文檔。
見文檔
見文檔
見文檔
【1】map(構造map對象)
Creates a map with the given key/value pairs. (key1,value1,key2,value2,…)
【2】struct(建立架構數組)
Creates a struct with the given field values. (val1,val2,val3,…)。Struct的屬性名和列名相對應。struct能夠認爲是面向對象的對象類型,是一個構造體,裏面能夠定義屬性的值,field的名稱是預先定義的,就像Java類的屬性預先定義好了。
【3】named_struct
Creates a struct with the given field names and values. (name1,val1,name2,val2, …)。根據給定的Struct的屬性名來建立構建數組
【4】array(建立數組對象)
Creates an array with the given elements. (val1,val2,val3,…)。把各(若干)個字段的值變成一個array。
【5】create_union
Creates a union type with value that is being pointes to by the tag parameter.
【1】A[n]
A是array類型,n是int類型。A[n]表示數組A的第n+1個元素。
【2】M[key]
M是map類型,key是map集合中鍵的類型。M[key]是取map集合中鍵爲key的值。注意使用是key須要使用單引號。
【3】S.x
S是struct類型,x表示struct中的某個屬性。S.x,將會返回S這個struct中定義的x屬性型中存儲的值。
略。
UDAF和UDF的區別在於傳給函數的參數不同。UDF表示傳給函數的參數只有一個值或一行值;UDAF是給函數傳多個值或者多行值的函數,例如count(*),sum(col)等都是多行的值。
UDAF(User- Defined Aggregation Funcation) 彙集函數,多進一出,例如count/max/min等。
詳見文檔。
HivePlugins,Creating Custom UDFs。自定義函數須要如下幾個步驟:首先要自定義一個類,繼承UDF;其次,打成jar包;第三,將jar包加載到hive的classpath;第四,建立自定義函數;第五,使用函數。
例如,要建立一個將字符串轉成日期的函數。
package com.huidoo.hive; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.hive.serde2.io.TimestampWritable; import org.apache.hadoop.io.Text; public class StringToDate extends UDF { /** * 定義evaluate方法。返回值類型定義爲TimestampWritable * @param str * @param datefmt * @return * @throws Exception */ public TimestampWritable evaluate(final Text str,final Text datefmt) throws Exception{ SimpleDateFormat sdf= new SimpleDateFormat(datefmt.toString()); //datefmt是傳入的格式化字符串,須要建立SimpleDateFormat對象,Text類型要轉成Java中的String類型。 Date date= sdf.parse(str.toString()); //將字符串str,按照格式sdf轉成java.util的Date類型 TimestampWritable time=new TimestampWritable();//建立Hadoop的時間戳對象 time.setTime(date.getTime());//將date轉成Timestamp類型,而後使用Hadoop時間戳對象設置成相應的時間。 return time; } }
略。std.jar
hive> add jar /path/to/std.jar;
語法:create 函數名(不能與內置的同樣) as ‘自定義類的全限定名’;
hive> create function std as 'com.huidoo.hive.StringToDate';
這就建立了一個函數,名爲std。
hive> select std('2016-02-06 01:19:30','yyyy-MM-dd HH:mm:ss') from t_log limit 3;
hive> select * from table_name;
查看當前數據庫:
hive> SELECT current_database();
"db_name.table_name" allows a query to access tables in different databases.能夠查詢不一樣數據庫中的表。
使用某數據庫:
hive> USE database_name;
hive>SELECT * FROM sales WHERE amount > 10 AND region = "US"
使用distinct關鍵字去重查詢,以下列出兩個查詢的區別:
hive> SELECT col1, col2 FROM t1
1 3
1 3
1 4
2 5
hive> SELECT DISTINCT col1, col2 FROM t1
1 3
1 4
2 5
join用於錶鏈接。兩個表即兩個文件能鏈接起來就必定有相同點,這就是說其中一個文件中某域的值和另外一個文件的某域的值相同,就能夠鏈接。
hive> select col1,col2,col3 from t1 join t2 on+條件;
這種查詢語法就只要把partition當成一個字段便可。若是查詢時要引入外鍵關聯表也可使用JION…ON語句。
語法:
hive> select table_name.* from table_name where table_name.partition_name +條件;
案例:
SELECT page_views.* FROM page_views WHERE page_views.date >= '2016-03-01' AND page_views.date <= '2016-03-31';
語法:
hive> select table_name1.* from table_name1 join table_name2 on (table_name1.外鍵 = table_name2.主鍵 And table_name1.partiton_name +條件);
案例:
SELECT page_views.* FROM page_views JOIN dim_users ON (page_views.user_id = dim_users.id AND page_views.date >= '2016-03-01' AND page_views.date <= '2016-03-31');
hive> select col[list] from table_name group by col;
sort by和order by的用法基本一致,都是作排序的,通常用order by。例如:
hive> select * from t_log order by id;
having從句必須依附於group by從句,在group從句後面接having從句,至關於增長一個條件。having後面能夠接聚合函數,例如sum、avg等。
hive> select day from t_log group by day;
其查詢結果爲:
2016-03-11
2016-03-12
hive>select day from t_log group by day having avg(id)>150;
其查詢結果爲:
2016-03-12
hive> select day from (select day, avg(id) as avgid from t_log group by day) table2 where table2.avgid>150;
這裏將t_log表經過select day, avg(id) as avgid from t_log group by day查詢獲得的結果做爲表再查詢的。和上述的hiving從句獲得的結果同樣。
限定查詢返回的行數。
hive> select * from t_log limit 5;