大數據入門第十一天——hive詳解(二)基本操做與分區分桶

1、基本操做

  1.DDLhtml

    官網的DDL語法教程點擊查看node

    建表語句算法

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]
data_type : primitive_type | array_type | map_type | struct_type | union_type  -- (Note: Available in Hive 0.7.0 and later)
 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)
 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, ... >  -- (Note: Available in Hive 0.7.0 and later)
數據類型

 說明:數據庫

    一、CREATE TABLE 建立一個指定名字的表。若是相同名字的表已經存在,則拋出異常;用戶能夠用 IF NOT EXISTS 選項來忽略這個異常。
    二、EXTERNAL關鍵字可讓用戶建立一個外部表,在建表的同時指定一個指向實際數據的路徑(LOCATION),Hive 建立內部表時,會將數據移動到數據倉庫指向的路徑;若建立外部表,僅記錄數據所在的路徑,不對數據的位置作任何改變。在刪除表的時候,內部表的元數據和數據會被一塊兒刪除,而外部表只刪除元數據,不刪除數據。
    三、LIKE 容許用戶複製現有的表結構,可是不復制數據。
    四、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
      若是文件數據是純文本,可使用 STORED AS TEXTFILE。若是數據須要壓縮,使用 STORED AS SEQUENCEFILE。apache

    六、CLUSTERED BY
      對於每個表(table)或者分區, Hive能夠進一步組織成桶,也就是說桶是更爲細粒度的數據範圍劃分。Hive也是 針對某一列進行桶的組織。Hive採用對列值哈希,而後除以桶的個數求餘的方式決定該條記錄存放在哪一個桶當中。
把表(或者分區)組織成桶(Bucket)有兩個理由:
    (1)得到更高的查詢處理效率。桶爲表加上了額外的結構,Hive 在處理有些查詢時能利用這個結構。具體而言,鏈接兩個在(包含鏈接列的)相同列上劃分了桶的表,可使用 Map 端鏈接 (Map-side join)高效的實現。好比JOIN操做。對於JOIN操做兩個表有一個相同的列,若是對這兩個表都進行了桶操做。那麼將保存相同列值的桶進行JOIN操做就能夠,能夠大大較少JOIN的數據量。
    (2)使取樣(sampling)更高效。在處理大規模數據集時,在開發和修改查詢的階段,若是能在數據集的一小部分數據上試運行查詢,會帶來不少方便。ide

    示例:工具

CREATE TABLE page_view(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(dt STRING, country STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\001' STORED AS SEQUENCEFILE;

     重命名錶oop

ALTER TABLE table_name RENAME TO new_table_name

    增長/更新列url

ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...) 注:ADD是表明新增一字段,字段位置在全部列後面(partition列前),REPLACE則是表示替換表中全部字段。 ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]

 

  2.DMLspa

    Load

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

      三、 LOCAL關鍵字

        若是指定了 LOCAL, load 命令會去查找本地文件系統中的 filepath。

        若是沒有指定 LOCAL 關鍵字,則根據inpath中的uri查找文件

      四、 OVERWRITE 關鍵字

       若是使用了 OVERWRITE 關鍵字,則目標表(或者分區)中的內容會被刪除,而後再將 filepath 指向的文件/目錄中的內容添加到表/分區中。

       若是目標表(分區)已經有一個文件,而且文件名和 filepath 中的文件名衝突,那麼現有的文件會被新文件所替代。

    insert

INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement Multiple inserts: FROM from_statement INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 [INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2] ... Dynamic partition inserts: INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement

     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]

    保存select 結果集的方式:

保存select查詢結果的幾種方式: 1、將查詢結果保存到一張新的hive表中 create table t_tmp as select * from t_p; 2、將查詢結果保存到一張已經存在的hive表中 insert into table t_tmp select * from t_p; 3、將查詢結果保存到指定的文件目錄(能夠是本地,也能夠是hdfs) insert overwrite local directory '/home/hadoop/test' select * from t_p; insert overwrite directory '/aaa/test' select * from t_p;

  3.hive join

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

   Hive中除了支持和傳統數據庫中同樣的內關聯、左關聯、右關聯、全關聯,還支持LEFT SEMI JOIN和CROSS JOIN,但這兩種JOIN類型也能夠用前面的代替。

   左半鏈接這裏給出一個示例,理論不贅述:參考這裏

 1 SELECT a.id, 2 a.name 3 FROM lxw1234_a a 4 LEFT SEMI JOIN lxw1234_b b 5 ON (a.id = b.id); 6 7 --執行結果: 8 1 zhangsan 9 2 lisi 10 11 --等價於: 12 SELECT a.id, 13 a.name 14 FROM lxw1234_a a 15 WHERE a.id IN (SELECT id FROM lxw1234_b);

 

 示例:

select * from a inner join b on a.id=b.id;

2、分區表與分桶表

  1.分區表

    在Hive Select查詢中通常會掃描整個表內容,會消耗不少時間作不必的工做。有時候只須要掃描表中關心的一部分數據,所以建表時引入了partition概念。分區表指的是在建立表時指定的partition的分區空間。 

Hive能夠對數據按照某列或者某些列進行分區管理,所謂分區咱們能夠拿下面的例子進行解釋。 
當前互聯網應用天天都要存儲大量的日誌文件,幾G、幾十G甚至更大都是有可能。存儲日誌,其中必然有個屬性是日誌產生的日期。在產生分區時,就能夠按照日誌產生的日期列進行劃分。把每一天的日誌看成一個分區。 
將數據組織成分區,主要能夠提升數據的查詢速度。至於用戶存儲的每一條記錄到底放到哪一個分區,由用戶決定。即用戶在加載數據的時候必須顯示的指定該部分數據放到哪一個分區。

    創建分區表

create table t_user_part (id int, name string) 
partitioned by (country string)
row format delimited fields terminated by '\t';

    向分區表中導入數據

[hadoop@mini1 ~]$ cat user.dat 1    Join
2 Mary 3 Bob 4    Tom
user.dat
LOAD DATA LOCAL INPATH '/home/hadoop/user.dat' INTO TABLE t_user_part PARTITION(country='USA');

0: jdbc:hive2://localhost:10000> SELECT * FROM t_user_part; +-----------------+-------------------+----------------------+--+ | t_user_part.id | t_user_part.name | t_user_part.country | +-----------------+-------------------+----------------------+--+ | 1 | Join | USA | | 2 | Mary | USA | | 3 | Bob | USA | | 4 | Tom | USA | +-----------------+-------------------+----------------------+--+ 4 rows selected (0.801 seconds) 0: jdbc:hive2://localhost:10000> 

   // 分區字段是一個僞字段

0: jdbc:hive2://localhost:10000> SELECT * FROM t_user_part WHERE country='USA';

    增長分區

ALTER TABLE table_name ADD partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ... partition_spec: : PARTITION (partition_col = partition_col_value, partition_col = partiton_col_value, ...) 用戶能夠用 ALTER TABLE ADD PARTITION 來向一個表中增長分區。當分區名是字符串時加引號。例: ALTER TABLE test_table ADD PARTITION (dt='2016-08-08', hour='10') location '/path/uv1.txt' PARTITION (dt='2017-08-08', hour='12') location '/path/uv2.txt';

    刪除分區

ALTER TABLE table_name DROP partition_spec, partition_spec,... 用戶能夠用 ALTER TABLE DROP PARTITION 來刪除分區。分區的元數據和數據將被一併刪除。例: ALTER TABLE test_table DROP PARTITION (dt='2016-08-08', hour='10');

    查看分區

show partitions tablename show partitions t_user_part;

   分區的更多介紹以及動態分區的介紹與設置:https://www.cnblogs.com/liqiu/p/4095654.html

  2.分桶表

  • 對於每個表(table)或者分區, Hive能夠進一步組織成桶,也就是說桶是更爲細粒度的數據範圍劃分。(桶有點相似mr中的分區)Hive也是針對某一列進行桶的組織。Hive採用對列值哈希,而後除以桶的個數求餘的方式決定該條記錄存放在哪一個桶當中。基本能夠這麼說分區表是粗粒度的劃分,桶在細粒度的劃分。當數據量比較大,咱們須要更快的完成任務,多個map和reduce進程是惟一的選擇。
  • 可是若是輸入文件是一個的話,map任務只能啓動一個。此時bucket table是個很好的選擇,經過指定CLUSTERED的字段,將文件經過hash打散成多個小文件。

    • 把表(或者分區)組織成桶(Bucket)有兩個理由:

      • 得到更高的查詢處理效率。桶爲表加上了額外的結構,Hive 在處理有些查詢時能利用這個結構。具體而言,鏈接兩個在(包含鏈接列的)相同列上劃分了桶的表,可使用 Map 端鏈接 (Map-side join)高效的實現。好比JOIN操做。對於JOIN操做兩個表有一個相同的列,若是對這兩個表都進行了桶操做。那麼將保存相同列值的桶進行JOIN操做就能夠,能夠大大較少JOIN的數據量。

      • 使取樣(sampling)更高效。在處理大規模數據集時,在開發和修改查詢的階段,若是能在數據集的一小部分數據上試運行查詢,會帶來不少方便

    注意:分桶以前要設置分桶開關以及reduce數量使其與分桶數量一致!

set hive.enforce.bucketing = true; set mapreduce.job.reduces=4;

  分桶表的相關操做,參考http://www.mamicode.com/info-detail-1781619.html

    創建分桶表:

create table t_buck(id int, name string) clustered by(id) sorted by(id) into 4 buckets row format delimited fields terminated by ',';
DESC EXTENDED t_buck;

    裝載數據:此種方式不會自動分桶,須要本身提早分桶,不建議使用!

LOAD DATA LOCAL INPATH '/home/hadoop/user2.dat' INTO TABLE t_user_buck;

    向這種帶桶的表裏面導入數據有兩種方式,一種是外部生成的數據導入到桶表,一種是利用hive來幫助你生成桶表數據。     

    開始往建立的分通表插入數據(插入數據須要是已分桶, 且排序的)

    可使用distribute by(id) sort by(id asc)

    排序和分桶的字段相同的時候也可使用Cluster by(字段)

    注意使用cluster by 就等同於分桶+排序(sort)

insert overwrite table t_buck select id,name from t_buck_from cluster by(id);

    

注:1order by 會對輸入作全局排序,所以只有一個reducer,會致使當輸入規模較大時,須要較長的計算時間。 2、sort by不是全局排序,其在數據進入reducer前完成排序。所以,若是用sort by進行排序,
  而且設置mapred.reduce.tasks>1,則sort by只保證每一個reducer的輸出有序,不保證全局有序。 3、distribute by(字段)根據指定的字段將數據分到不一樣的reducer,且分發算法是hash散列。 4、Cluster by(字段) 除了具備Distribute by的功能外,還會對該字段進行排序。 5、建立分桶表並不意味着load進數據也是分桶的,你必須先分好桶,而後再放到表中。

 

0: jdbc:hive2://localhost:10000> dfs -cat /user/hive/warehouse/t_buck/000001_0; +-------------+--+ | DFS Output | +-------------+--+ | 1,aa | | 5,ee | | 9,ii | +-------------+--+ 3 rows selected (0.032 seconds) 0: jdbc:hive2://localhost:10000> 

  分桶表的最大做用是提升了表之間的join效率,由於兩個分桶表之間join的字段只需對應桶便可!

  具體分析與操做,參考https://www.cnblogs.com/kouryoushine/p/7809299.html

相關文章
相關標籤/搜索