Hive初識

Hive

Hive是什麼

  • Hive是一個SQL解析引擎,將SQL語句轉譯成MRJob,而後再在Hadoop平臺上運行,達到快速開發的目的。
  • Hive中的表,是純邏輯表,它自己不存儲數據,只存儲表的定義即表的元數據信息。本質就是Hadoop的目錄/文件,所以達到元數據和數據存儲相分離的目的。
  • Hive因爲自己不存儲數據,所以徹底依賴HDFS和MR。
  • Hive不支持數據的修改和刪除。
  • Hive中的數據格式由用戶指定,須要指定三個參數:sql

    • 列分隔符:空格(" ")、逗號(",")、製表符("t")
    • 行分隔符:換行符("n")
    • 讀取文件數據的方法

爲何用Hive

  • 對於存儲在HDFS上的文件或Hbase上的表進行查詢時,使用單純的MR須要寫大量MapReduce代碼
  • 對於一些統計任務,只能由懂MapReduce的人才能完成
  • 任務繁重,效率低

Hive SQL 和 傳統的 SQL 對比

語言 HQL SQL
數據存儲 HDFS Hbase Local FS
數據格式 用戶自定義 由系統決定
數據更新 不支持(會覆蓋) 支持
索引 有(0.8版後新增)
執行 MR Executor
執行延遲
可擴展性 高(UDF、UDAF、UDTF)
數據規模 大(數據大於TB)
數據檢查 讀時模式 寫時模式

Hive體系架構

Hive建表

內部表

//建內部表
create table inner_test (name String) 
row format delimited fields terminated by '\n';
//導入數據
load data local inpath 'local/path' into table inner_test;

外部表

//建外部表
create external table external_test (name String) 
row format delimited fields terminated by '\n'
-- stored as textfile
location 'local/path';//必須是文件

內部表和外部表的區別

  • 內部表被drop後,Hive、hdfs中的元數據和文件數據都會同時被刪除。即:內部表是由Hive本身管理的
  • 外部表被drop後,Hive中的元數據信息會被刪除,可是,指定的外部文件的文件數據還在。即:外部表不是Hive管理的。

分區表

  • Hive中,分區表的一個partition對應於表下的一個目錄,全部partition數據都存儲在對應的目錄中架構

    • 如:表 tablea 中有兩個分區 p1 和 p2,則:app

      對應的 p1='aaa',p2='111' 的目錄爲: xxx/tablea/p1=aaa/p2=111;
        對應的 p1='aaa',p2='222' 的目錄爲: xxx/tablea/p1=aaa/p2=222;
  • partition能夠輔助查詢,做爲查詢條件,加快查詢速度
  • SQL語句:
//建分區表,按dt分區
create table partition_test (name String) 
partitioned by (dt String) 
row format delimited fields terminated by '\n';
//插入數據
insert overwrite table partition_test 
partition (dt='xxx')
select * from partition_from
limit 1000;
//查看分區表分區信息
show partitions partition_test;
//通常狀況下,分區表數據由定時任務插入

分桶

  • Hive中, table 能夠分紅 partition ,而 table 和 partition 能夠進一步分桶 bucket,使用 'clustered by',在桶內的數據可使用 'sort by' 排序。(order by能夠嗎???todo)
  • 分桶SQL:ide

    //建分桶表
    create table bucket_test (num int)
    clustered by (num) into 32 buckets;
  • 分桶主要做用:函數

    • 進行數據採樣
    • 提高某些查詢操做的效率,例如: mapside join
  • 設置參數: set hive.enforce.bucketing = true; 能夠自動控制上一輪 reduce 的數量從而適配 bucket 個數。同時,也能夠自主設置 mapred.reduce.tasks 去適配 bucket 個數。

分桶採樣

  • 語法: tablesample(bucket x out of y on num)
  • 假設:共 num 個桶,則:從第 x 個桶開始,取 num/y 個桶的數據
  • SQLoop

    select * from bucket_test
    tablesample (bucket 1 out of 32 on 32) ;

咱們假設分桶表 bucket_test 裏的數據是 '1,2,3,4,5,6,7...32', 那麼,執行上面 sql 後會返回什麼呢?
運用採樣公式,得知:共有 32 個桶,會從第一個桶開始取數據,共取 32/32=1 個數據。而桶的下標是從 0 開始的,則得出採樣結果: 32(第一個桶(下標爲0)內的數據是 32 )。
咱們換一下采樣sql,改成:tablesample(bucket 1 out of 16 on 32); 結果會是什麼?
一樣,利用採樣公式得知:共有 32 個桶,會從第一個桶開始取數據,共取 32/16=2 個數據。一個桶內只有一個數據,那麼,另外一個數據取哪一個桶裏的呢?
咱們能夠將桶分爲兩部分,每部分 16 個,因此,取每部分的第一個桶,對應到 32 個桶上,就是第一個和第十七個,即:3二、16。code

  • 沒有分桶的表,如何採樣90%的數據?regexp

    select * from tablename where num % 10 > 0;
    //若是是字符串的話,須要先 hash 轉成數字。

動態插入分區表

  • 設置參數:orm

    • set hive.exec.dynamic.partition = true; //使用動態分區
    • set hive.exec.dynamic.partition.mode = nonstrict; //使用無限制模式

Hive經常使用函數

  • split:切分。如:"aaa_bbb".split("_") 按照下劃線切分。
  • explode:將列數據按行輸出。
  • regexp_extract:正則匹配。如:regexp_extract('string', '[[\w]]+', 0)
  • ceil:向上取整
  • collect_list:聚合。如:collect_list(column) -> ['1','2','3',....]
  • concat_ws:拼接。如:concat_ws('_', column1, column2) as t
  • row_number:行號,連續值。(1,2,3,4,5,....)
  • rank:排序相同時,會重複,總數不變。(1,1,3,4,5,5,5,8,...)
  • dense_rank:排序相同時,會重複,總數減小。(1,1,2,2,2,3,4,5,5,6...)

sort by 和 order by

  • sort by:在同一個 reduce 中進行排序
  • order by:全局排序,通常只有一個 reduce

partition by 和 distribute by

  • partition by xx order by xx :partition by 和 order by 組合
  • distribute by xx sort by xx :distribute by 和 sort by 組合

partition by 和 group by 的使用場景

  • partition by:須要搭配 over 使用,原來數據有多少條 user_id ,結果還有多少條排序

    select user_id, count(order_id) over(partition by user_id)
    from orders;
  • group by:因爲聚合,最終一個 user_id 只有一條數據

    select user_id, count(order_id) 
    from orders
    group by user_id;

tip點

  • order by 佔用一個 mapreduce
  • 打印表頭: set hive.cli.print.header=true;
  • 若是設置參數不生效,要知道,設置的參數也有優先級
  • 經常使用的分區字段有:①日期 ②客戶端類型(pc、m、app)
相關文章
相關標籤/搜索