Hive 編程之DDL、DML、UDF、Select總結

  Hive的基本理論與安裝可參看做者上一篇博文《Apache Hive 基本理論與安裝指南》。html

1、Hive命令行

  全部的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

2、Hive DDL(Data Definition Language)

  詳見官方文檔。重點在於建立表和建立函數。vim

1. 建表語法

  • 建表語句

  從官方文檔的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
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
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是默認的格式,文本格式。

2. 建立表案例一  

  • 查看數據

  爲舉例說明,這裏先生成數據文件:

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
hive> load data local inpath '/root/person.txt' into table t_person;
  • 查看數據

 

3. 建立表案例二(分區表)

  當咱們要在關係型數據庫中查找某一數據時,通常須要匹配數據庫中的全部數據,因此能夠經過分區來提升查詢效率。把經常使用的查詢條件做爲一種分區,例如要查某一天的數據,事實上就是能夠只匹配當天的數據,其餘數據不匹配。下面以建一個日誌管理表爲例:

  • 數據文件

  文件常常按照天、小時等進行分割。故在此建立多個文件以下:

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';

  固然,這裏須要先轉換格式,略。

3、Hive DML(Data Manipulation Language)

  詳見官方文檔。DML是對數據進行增刪改的腳本。可是數據在hdfs中,實際上不提供修改,只提供追加(insert),支持刪除。

1. Loading files into tables

  • 語法

  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。

  • 實例
    • 將hdfs中的數據裝載到hive  

  首先,上傳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。文件中的數據格式要和表的結構相吻合。

    • 將Linux本地的數據裝載到hive
hive>load data local inpath '/root/log_2016-03-11.txt' into table t_log partition (day='2016-03-11');

2. Inserting data into hive tables from queries

  • 語法
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語句的實際意義在於將查詢結果放到新的表中。

3. Delete

  刪除數據通常能夠不在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

4、Hive UDF(Operators and User-Defined functions)

  詳見官方文檔

1. 內置運算符

  • 關係運算符

  見文檔

  • 算術運算符

  見文檔

  • 邏輯運算符

  見文檔

  • 複雜類型構造函數(Complex Type Constructors)
    • 複雜類型函數或對象的構建

  【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屬性型中存儲的值。

2. 內置函數

  • 數學函數

  • 集合操做函數

  • 類型轉換函數

  • 日期函數

  • 條件/邏輯函數

   略。

  • 字符串函數

3. UDAF

  UDAF和UDF的區別在於傳給函數的參數不同。UDF表示傳給函數的參數只有一個值或一行值;UDAF是給函數傳多個值或者多行值的函數,例如count(*),sum(col)等都是多行的值。

  UDAF(User- Defined Aggregation Funcation) 彙集函數,多進一出,例如count/max/min等。

4. UDTF

  詳見文檔。

5. UDF

  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;
    }
}
  • 打成jar包並上傳到服務器

  略。std.jar

  • 將jar包加載到hive的classpath
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;

5、Hive Select

1. 簡單查詢和使用/切換數據庫

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;

2. where從句

hive>SELECT * FROM sales WHERE amount > 10 AND region = "US"

3. ALL and DISTINCT從句

  使用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

4. Join從句

  join用於錶鏈接。兩個表即兩個文件能鏈接起來就必定有相同點,這就是說其中一個文件中某域的值和另外一個文件的某域的值相同,就能夠鏈接。

hive> select col1,col2,col3 from t1 join t2 on+條件;

5. 基於Partition的查詢

  這種查詢語法就只要把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');

6. Group by從句

hive> select col[list] from table_name group by col;

7. Order/Sort by從句

  sort by和order by的用法基本一致,都是作排序的,通常用order by。例如:

hive> select * from t_log order by id;

8. Having從句

  having從句必須依附於group by從句,在group從句後面接having從句,至關於增長一個條件。having後面能夠接聚合函數,例如sum、avg等。

  • 單純的group by語句
hive> select day from t_log group by day;

  其查詢結果爲:

  2016-03-11

  2016-03-12

  • 添加having從句
hive>select day from t_log group by day having avg(id)>150;

  其查詢結果爲:

  2016-03-12

  • hiving同效於子查詢
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從句獲得的結果同樣。

9. Limit從句

  限定查詢返回的行數。

hive> select * from t_log limit 5;
相關文章
相關標籤/搜索