Hive的一些理解


首先談一下關於hive和hbase的區別的疑問(完全不是一個東西):

  本質上來說hive和hbase沒什么關系,雖然都是表,查數據等,但是他們根本就不是一個層面的東西

  hive就是一個rapduce的一個包裝,hive就是將編寫的sql轉換成mapreduce任務

  而hbase是什么呢?可以理解為是hdfs的一個包裝,本質是數據存儲的,一個nosql數據庫,部署與hdfs之上的,目的是克服hdfs在隨機讀寫上的缺點

  你非得問hive和hbase有什么區別,那就相當於問mapreduce和hdfs有什么區別,所有談他們的區別完全沒有任何的意義

引入Hive原因:

  – 對存在HDFS上的文件或HBase中的表進行查詢時,是要手工寫一堆MapReduce代碼

  – 對於統計任務,只能由動MapReduce的程序員才能搞定

Hive基於一個統一的查詢分析層,通過SQL語句的方式對HDFS上的數據進行查詢、統計和分析  

  由此可以看出來hive適合做數據查詢、統計和分析,使用SQL語句(但是,hive的sql並不是一個標准的sql,只是類似於一個標准的sql,但不等價於一個標准的sql)對HDFS進行查詢(mapreduce也是對HDFS進行查詢等工作,所以hive本身並不會存儲數據

Hive到底是什么?

  hive是基於Hadoop的一個數據倉庫工具,可以將結構化的數據文件映射為一張數據庫表,並提供簡單的sql查詢功能,可以將sql語句轉換為mapreduce任務進行運行。 

  Hive中的表是純邏輯表,就只是表的定義等,即表的元數據。本質就是Hadoop的目錄/文件,達到了元數據與數據存儲分離的目的

  Hive本身不存儲數據,它完全依賴HDFS和MapReduce

  Hive的內容是讀多寫少,不支持對數據的改寫和刪除(0.14版本以后支持更新,但是得開啟,默認關閉。由此可見hive不適合更新,因為hdfs也不適合修改!hdfs數據要修改,要么就是刪除,要么就是追加,考慮到性能,大數據不建議頻繁修改和刪除

  Hive中沒有定義專門的數據格式,由用戶指定,需要指定三個屬性:

    – 列分隔符 :       空格,  \t , \001

    – 行分隔符:  \n

    – 讀取文件數據的方法: TextFile ,SquenceFile,RCFile

      TextFile(優點:可讀性好。缺點:占內存空間,磁盤開銷大)--------python,Streaming開發一般是這種格式

      SquenceFile(二進制,是hadoop提供的一種二進制文件,<key,value>形式序列化到文件中,Java Writeable接口進行序列化和反序列化)------java開發一般是這種格式

      RCFile(是Hive專門推出的,一種面向列的數據格式)---------實際上在mapreduce的map階段遠程拷貝的時候,本質是拷貝block,但是block依然是整個的數據,block沒辦法具體區分哪一個列,讀過來就是全讀,所以性能並不一定比TextFile好

為什么選擇hive?

    看一個wordcount

      select word,count(*) form (select  exploed(sentence, ' ') as word form article) t group by word

    一行sql實現了一個單詞計數,大量節省開發和學習成本,而且便於修改

Hive 中 的 sql 與傳統 sql 區 別:

     

    函數:

      UDF:直接應用於select語句,通常查詢的時候,需要對字段做一些格式化處理(例如:大小寫轉換,比如表里都是小寫,但是就想顯示全是大寫)

          特點:一進一出,一對一的關系

      UDAF:多對一的關系,通常用於group by階段

      UDTP:一對多

    讀時模式:只有hive讀的時候才會檢查,解析字段和schema(數據結構的表達)

        優點:load data非常迅速,因為在寫的過程中不需要解析數據 

    寫時模式:

        優點:讀的時候會得到優化

        缺點:寫的慢,需要建立一些索引,壓縮,數據一致性,字段檢查等...

與傳統關系數據特點比較:

    hive和關系數據庫存儲文件的系統不同,hive使用的是hadoop的HDFS(hadoop的分布式文件系統),關系數據庫則是服務器本地的文件系統

    hive使用的計算模型是mapreduce,而關系數據庫則是自己設計的計算模型

    關系數據庫都是為實時查詢的業務進行設計的,而hive則是為海量數據做數據挖掘設計的,實時性很差

    Hive很容易擴展自己的存儲能力和計算能力,這個是繼承hadoop的,而關系數據庫在這個方面要比數據庫差很多

Hive體系架構:

    

  分為三個部分:

    用戶接口:

      CLI:client(Hive 的客戶端,用戶連接至 Hive Server,一般是linux下)進行交互執行sql,直接與Driver進行交互。

      JDBC:Hive提供JDBC驅動,作為JAVA的API:JDBC是通過Thrift Server來接入,然后發給Driver

      GUI:通過瀏覽器訪問 Hive 

    語句轉換(Driver------->hive本身並不會生成mapreduce,而是通過一個執行計划來執行mapreduce(xml----->mapper,reducer模塊)):

      解析器:生成抽象語法樹

      語法分析器:驗證查詢語句

      邏輯計划生成器(包括優化器):生成操作符樹

      查詢計划生成器:轉換為map-reduce任務

    元數據:

      metastore------>是一個獨立的關系型數據庫,默認的數據庫是derby(單用戶常用)。真正的生產都是遠程服務模式----->mysql

    數據存儲:

      Hive數據以文件形式存儲在HDFS的指定目錄下

      Hive語句生成查詢計划,由MapReduce調用執行

Hive數據管理:

    hive的表本質就是Hadoop的目錄/文件

    – hive默認表存放路徑一般都是在你工作目錄的hive目錄里面,按表名做文件夾分開,如果你有分區表的話,分區值是子文件夾,可以直接在其它的M/R job里直接應用這部分數據

Hive有四種數據模型:  

     數據表:

      Table:內部表

      External Table:外部表

     分區表:

      Partition

      Bucket

  Table:

    和傳統數據庫概念基本一致,都是一個數據表,但是每一個table在hive中都會有一個目錄來存取數據

    例如: 有表user ,因為hive不存儲數據,都是在hdfs上,所以路徑就在/warehouse/user/(注意:user不是一個文件,是一個目錄

  Partition:

    相當於分桶

      好處:通常查詢的時候會掃描整個表的內容,那就會消耗很多的時間

      例如:select xxx form table where date='2019-03-07' limit 100   通常查詢時候都會有where條件,但是這樣查詢也會掃描8,9....等等的數據,但是8,9號的數據對我們要查的來說完全沒有意義,我們只需要7號的數據

      引入partition能大大優化性能,分區表需要在創建表的時候引入一個partition的分區的空間,一個表可以有一個或多個分區,然后以單獨的文件夾的形式存在表的文件夾下面(wherehorse/user/partition)

    通常什么字段能做為分區字段呢?

      不是所有的字段都適合做分區

      1.通常這個字段是經常在where條件中做過濾用的

      2.取值范圍有點集合的字段(假設用戶名做分區,那將會有無數個小文件,然而小文件會占用namenode內存區域,關於hdfs為什么不適合大量存儲小文件,如果有時間會寫hdfs的內容)

      假設要對一天的數據做統計:

      那就按照天做分區  day=20190307   路徑位置/warehouse/table/20190307/

      查詢的時候where條件就成了一個文件夾了,然后對里面的內容做查詢就可以了,不用查詢其他的天數了

      當多個字段做分區的時候,會按照笛卡爾迪的形式   action=insight,  day=20190307    路徑/warehouse/table/insight/20190307

  Bucket:

   開啟bucket:set hive.enforce.bucketing = true

   Hive會針對某一個列進行桶的組織,通常對列值做hash

     假設:想存userid,然后這張表太大了,但是又想存數據,又不想突破一張表的的上限

     分庫:把一張表拆分成多個表

     例如:分32庫,userid%32=桶號

       表名:table

       分庫后表名:table_0,table_1,table_2,table_3......table_32

       每張表都不會重復,因為按照userid做的分桶

     路徑/warehouse/table/partition/part-00000

   bucket有什么作用呢?

     1.優化查詢

     2.方便采樣

     假設兩張表,id相同,分區相同,當做join的時候,只需要join目標id相同的分桶就可以,其他的桶不需要理會,性能大大優化

     兩個分區表做join,他會自動激活map端的 (map-side Join)

Hive的內部表和外部表:

    內部表:create table

    外部表:create external table

內部表和外部表的區別:

    內部表刪除,表結構和數據都刪除

    外部表刪除,只刪除表結構,不刪除數據(刪除外部表怎么恢復?重新創建表)

    - 在導入數據到外部表,數據並沒有移動到自己的數據倉庫目錄下,也就是說外部表中的數據並不是由它自己來管理的!而表則不一樣;

    - 在刪除表的時候,Hive將會把屬於表的元數據和數據全部刪掉;而刪除外部表的時候,Hive僅僅刪除外部表的元數據,數據是不會刪除的!

Hive的數據類型:

  基礎類型:

      • TINYINT

      • SMALLINT

      • INT

      • BIGINT

      • BOOLEAN

      • FLOAT

      • DOUBLE

      • STRING

      • BINARY(Hive 0.8.0以上才可用)

      • TIMESTAMP(Hive 0.8.0以上才可用)

  復合類型:

      • Arrays:ARRAY<data_type>

      • Maps:MAP<primitive_type, data_type>

      • Structs:STRUCT<col_name: data_type[COMMENT col_comment],……>

      • Union:UNIONTYPE<data_type, data_type,……>

  

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM