hive入門總結

1.hive入門
2.hive基礎操作
3.hive高階知識
4.hive的調優及權限控制
5.hive常見面試問題

hive入門
        爲什麼會出現hive
                要想利用Hadoop處理大數據,需要Java基礎知識,開發mapreduce時比較耗費時間,需要編碼測試打包部署,非常麻煩,
                所以facebook的工程師們想使用一種工具像使用sql一樣對海量數據進行統計分析,所有hive就誕生了。
        hive是什麼
                1.hive建立在Hadoop上的數據倉庫基礎架構。是一種可以存儲,查詢和分析存儲在Hadoop中的大規模數據的機制。
                2.hive是sql的解析引擎,他將sql語句轉譯成M/R job 在Hadoop上執行。
        hive的系統結構和數據存儲
                hive是數據倉庫(不是數據庫)。
                hive定義了簡單的SQL查詢語言HQL(sql方言),
                同時hive允許屬性mapreduce的開發者使用mapper和reducer來處理分析工作。
                
                系統結構:
                        1.用戶接口:
                                CLI,JDBC/ODBC,WebGUI分別對應,shell命令,Java訪問,瀏覽器訪問
                        2.元數據存儲
                                hive將元數據存儲在MySQL,derby(默認),主要存儲的是表的名字,表的列分區,表的屬性(外部表還是受控表),
                                表所在的目錄等不存儲數據。
                        3.解釋器,編譯器,優化器,執行器
                                完成hql查詢語句,從詞法分析,語法分析,編譯,優化以及查詢計劃的生成,將生成的查詢計劃存儲在hdfs中,由mapredce調用。
                        4.hadoop
                                hive的數據存儲在hdfs中,大部分查詢由mapreduce完成(select * from table 不會生成mapreduce任務)                                
                hive的數據存儲        
                        hive的數據存儲基於Hadoop HDFS
                        存儲結構主要包括:數據庫,文件,表視圖,索引
                        hive默認可以直接加載文本文件(TextFile),還支持SequenceFile,RCFile
                        創建表時可以指定數據的列和行的分割符。
        hive的安裝
                由於默認的derby數據庫一次只能打開一個會話,不方便所有,使用MySQL。                
                1、Linux MySQL安裝:
                在線安裝Mysql
                        1°、查看mysql的依賴
                                rpm -qa | grep mysql
                        2°、刪除mysql的依賴
                                rpm -e --nodeps `rpm -qa | grep mysql`
                        3°、yum安裝mysql
                                yum -y install mysql-server
                        4°、啓動mysql服務
                                service mysqld start
                        5°、加入到開機啓動項
                                chkconfig mysqld on
                        6°、初始化配置mysql服務
                                whereis mysql_secure_installation
                                執行腳本/usr/bin/mysql_secure_installation
                        7°、訪問mysql服務
                                mysql -uroot -proot
                                mysql -h ip -u密碼 -p密碼
                                        
                離線安裝Mysql
                        1°、查看mysql的依賴
                                rpm -qa | grep mysql
                        2°、刪除mysql的依賴
                                rpm -e --nodeps `rpm -qa | grep mysql`或者
                                rpm -e --nodeps `rpm -qa | grep MySQL`
                        3°、離線安裝mysql
                                rpm -ivh MySQL-server-5.1.73-1.glibc23.x86_64.rpm
                                rpm -ivh MySQL-client-5.1.73-1.glibc23.x86_64.rpm
                        4°、啓動mysql服務
                                service mysql start
                        5°、加入到開機啓動項
                                chkconfig mysql on
                        6°、初始化配置mysql服務
                                whereis mysql_secure_installation
                                執行腳本/usr/bin/mysql_secure_installation
                        7°、訪問mysql服務
                                mysql -h ip -u密碼 -p密碼
                                        問題:Host '' is not allowed to connect to this MySQL server
                                        解決辦法:
                                                mysql> grant all privileges on *.* to 'root'@'%' identified by 'root';
                                                mysql> flush privileges;
                                                
                安裝mysql時如果之前安裝過,初始化時mysql_secure_installation 
                如果讓輸入密碼輸入之前的密碼才能進行之後的配置,之後設置的密碼纔是本次用戶密碼;
                還可以殺掉所有mysql進程解決 ps -ef |grep mysql 查看mysql進程。
                
                2、安裝Hive
                前提是:hadoop必須已經啓動了
                1°、解壓hive的安裝包
                         tar -zxvf apache-hive-0.14.0-bin.tar.gz -C ../
                2°、備份配置文件
                        cp hive-env.sh.template hive-env.sh
                        cp hive-default.xml.template hive-site.xml
                3°、配置hive的配置文件
                        1)、修改hive-env.sh
                                加入三行內容
                                        JAVA_HOME=/usr/local/jdk1.7.0_55
                                    HADOOP_HOME=/usr/local/hadoop-2.4.1
                                    HIVE_HOME=/usr/local/hive-0.14.0
                        2)、修改hive-site.xml
                                <property>
                                        <name>javax.jdo.option.ConnectionURL</name>
                                        <value>jdbc:mysql://ip:3306/hiveexample?createDatabaseIfNotExist=true</value>
                                </property>
                                <property>
                                        <name>javax.jdo.option.ConnectionDriverName</name>
                                        <value>com.mysql.jdbc.Driver</value>
                                </property>
                                <property>
                                        <name>javax.jdo.option.ConnectionUserName</name>
                                        <value>root</value>
                                </property>
                                <property>
                                        <name>javax.jdo.option.ConnectionPassword</name>
                                        <value>root</value>
                                </property>
                                <property>
                                        <name>hive.querylog.location</name>
                                        <value>/usr/local/hive-0.14.0/tmp</value>
                                </property>
                                <property>
                                        <name>hive.exec.local.scratchdir</name>
                                        <value>/usr/local/hive-0.14.0/tmp</value>
                                </property>
                                <property>
                                        <name>hive.downloaded.resources.dir</name>
                                        <value>/usr/local/hive-0.14.0/tmp</value>
                                </property>
                4°、拷貝mysql驅動到$HIVE_HOME/lib目錄下
                        cp /usr/local/soft/mysql-connector-java-5.1.39.jar $HIVE_HOME/lib/
                5°、啓動Hive(可以加入環境變量)
                        腳本文件方式 hive 
                        命令行方式cli:控制檯模式 hive --service cli
                        JDBC方式:hiveserver  (hive --service hiveserver2)
                        web GUI接口 hwi方式


        hive的操作:
                hive的操作大部分和MySQL差不多                
                數據庫操作
                        創建數據庫: create database dbName;
                        刪除數據庫: drop database dbName;
                        瀏覽所有數據庫: show databases;
                        查看具體的數據庫: desc [extended] database dbName;
                        使用數據庫:use 數據庫名;不使用的話默認使用default
                表操作
                        創建一張表
                                create table t1(id int comment "ID");
                        瀏覽所有表
                                show tables;
                        修改表中的某一列
                                mysql: alter table t1 change id df ;
                                hive:alter table t1 change column col new_col type;
                                eg. hive>alter table t1 change column id ids int comment "IDS";
                        增加列
                                hive> alter table t1 add columns(name string, age int, gender string);
                        刪除列:hive中做不到,可以使用列替換
                         hive> alter table t1 replace columns(id int, name string, age int);
                        列的移動:
                                可以將hive表中的其中一列移動表中的任何位置:
                                first:將表中的一列移動到第一列
                                eg:alter table t1 change column gender gender string first;將gender移動到第一列
                                after:將表中的一列移動到另一列的後面
                                eg:alter table t1 change column gender gender string after age;將gender移動到age的後面
                                注意:沒有before和last。
        hive的數據類型        
                表中如何加載數據:
                (1)、從本地文件系統中導入數據到Hive表;
                (2)、從HDFS上導入數據到Hive表;
                (3)、從別的表中查詢出相應的數據並導入到Hive表中;
                (4)、在創建表的時候通過從別的表中查詢出相應的記錄並插入到所創建的表中。
                        hive數據在Hadoop中是目錄文件的形式。
                        load data local inpath 'linux-path' into table tblName;
                        hive> load data local inpath 'hadoop路徑下文件或者linux路徑文件' into table t;
                        也可以使用hadoop fs -put linux-path hive-table-dir
                        列的默認分隔符:\001
                        hive> insert into table test select id, name, tel from wyp;
                        hive> create table test11 as  select id, name, tel from wyp;

                數據的加載模式
                        讀模式
                                就是說數據在被加載的時候,對數據的合法性進行校驗,當在查詢的時候,將不合法的數據顯示爲NULL。
                                好處:數據加載的速度快,適合加載大數據。
                        寫模式
                                就是說數據在被加載的時候,需要對其合法性進行校驗,校驗失敗,則加載失敗,在數據中的數據都是合法的。
                                好處:適合關係型數據的使用,對數據的準確性要求高。
                        hive使用的是讀模式,當非法數據時顯示null。
                        
                自定義的分隔符:
                        create table t(
                                id int comment "ID",
                                name string comment "student's name",
                                birthdate date comment "student's birthdate",
                                
                        ) 
                        row format delimited
                        fields terminated by '\t'--自定義列分隔符tab。默認分隔符是:\001,在shell中輸入使用:ctrl+v,ctrl+a
                        lines terminated by '\n';
                複合數據類型
                array
                        create table t_arr(
                                id int comment "ID",
                                name string comment "student's name",
                                hobby array<string> comment "hobbies"
                        )
                        row format delimited
                        fields terminated by '\t'
                        collection items terminated by ','
                        lines terminated by '\n';
                        引用array數據中的元素
                                select id, name, hobby from t_arr;

默認的集合元素分隔符是:\002,在shell中輸入使用:ctrl+v,ctrl+b
                map
                        create table t_map (
                                id int comment "ID",
                                name string comment "student's name",
                                score map<string, float>
                        )
                        row format delimited
                        fields terminated by '\t'
                        collection items terminated by ','
                        map keys terminated by ':';
                        如何引用map的元素
                                map_name["keyName"]
                                select score["chinese"] from t_map;
                        map數據類型也有自己的默認分隔符:\003  --ctrl+v,ctrl+c
                struct                        
                        create table t_struct(
                                id int comment "ID",
                                name string comment "student's name",
                                jguan struct<province:string, city:string, zip:int> comment "籍貫"
                        )
                        row format delimited
                        fields terminated by '\t'
                        collection items terminated by ','
                        lines terminated by '\n';
                        結構體複合數據類型的自定義分隔符的定義和array的一樣的,在
                                引用的時候使用:結構體名.屬性名                
                        select id, name, jguan.province from t_struct where jguan.province like 'shanghai'; 

        hive表的分類:
                受控表(內部表,管理表):
                        刪除表時元數據和表數據都被刪除。加載數據的過程是數據被移動到數據倉庫目錄中,
                        之後的訪問都是在數據倉庫目錄中完成的。/user/hive/warehouse默認的數據倉庫目錄 hdfs dfs -ls /user/hive/可以查看。
                         可以創建平級目錄的數據庫create database mydb2 location '/user/hive/mydb2';
                        type:MANAGED_TABLE
                外部表 :
                        表數據的生命週期不受表定義的影響,只是與外部表建立一個鏈接,刪除外部表時,僅刪除鏈接,
                        刪除的是metastore的元數據,不刪除hdfs中的表數據。
                        type:EXTERNAL_TABLE
                        創建外部表:create external table t6_external(id int);
                        外部表加載數據:alter table t6_external set location "hdfs_path";
                        創建外部表的同時指定數據:create external table t6_external_1(id int) location "hdfs_path_dir";
                        注意:
                        alter的方式,location必須爲絕對路徑
                        create的方式,location必須爲目錄
                爲什麼使用外部表:
                        當操作的數據是共有數據時一般都用外部表。減少冗餘,數據安全防止誤刪。
                        hive--hbase 關聯hbase一般使用外部表
                內外部表之間的轉換:
                內-->外:
                        alter table t1 set tblproperties("EXTERNAL"="TRUE");  
                外部表-->內:
                        alter table t1 set tblproperties("EXTERNAL"="FALSE");
                當一個外部錶轉化成爲內部表,如果刪除這個內部表,則其原先引用的數據也一併被刪除。
        分區表:
                爲什麼使用分區表:
                        當表的數據過大時,我們就按照特定的規律可以將講一個大表使用分區拆分成不同的小表提高查詢效率
                        例如按天分區就會一天產生一個文件
                創建分區表:
                create table t_partition(id int) partitioned by(dt date comment "一天一個分區");
                加載數據:
                        load data local inpath '文件路徑' into table t partition(dt="2016-07-25");                
                多個分區:
                        create table t_partition(id int, name string) 
                        row format delimited
                        fields terminated by '\t'
                        partitioned by(year int comment "年份", school string comment "院系");
        分桶表
                爲什麼使用桶:
                        數據傾斜會出現有些地方數據很大,有些數據很小,儘量均勻分佈存儲數據
                桶表用處:抽樣;提高查詢速率
                原理:對數據進行哈希取值,然後放到不同的文件中存儲。
                創建分桶表:
                        create table t_bucket(id int) clustered by(id) into 3 buckets;
                        對字段id取哈希值,然後與捅數量3取模。把數據放到對應的文件中。
                        物理上一個桶就是表目錄裏的一個文件。一個作業產生的桶和reduce任務數相同
                加載數據:
                        要想對分桶表中的數據進行一個分桶,必須從別的表進行轉化。
                        insert into table t_bucket select id from t_partition where dt="2016-07-25";
                        這條sql注意一點的是:前後的列一定要對應。
                注意:
                        hive.enforce.bucketing=true                        
        Hive中的視圖:        
                總結一句話:方便查詢,隱藏細節(數據安全)
                官腔:  1、 視圖能夠簡化用戶的操作
                        2、 視圖使用戶能以多鍾角度看待同一數據
                        3、 視圖對重構數據庫提供了一定程度的邏輯獨立性
                        4、 視圖能夠對機密數據提供安全保護
                        5、 適當的利用視圖可以更清晰的表達查詢
                create view t_view as select id from t_partition where dt="2016-07-25";        
        Hive中MR的本地模式
                可以縮短mr的執行時間。但是有大小限制 128M
                set hive.exec.mode.local.auto=true;
                在進行測試進行使用。                
        Hive數據加載和導出   []表示可選,<>表示必須
        數據的加載
                load data [local] inpath 'path' [overwrite] into table tblName [partition partition_sepc];
                        local:     有:數據從linux本地path去加載數據
                                      無:數據到hdfs的相關目錄path下去加載數據,相當於hadoop fs -mv 
                        overwrite:  :刪除原來的數據,新增一份
                                            :在原來的基礎上追加一份
                從其他的表加載數據
                        insert <overwrite|into> table t8_bucket select id from t7_partition where dt="2016-07-25";
                在創建表的時候加載數據
                        create table tblName as select cols from oldTbl;
                        另外的:可以通過like來快速的複製一張表的結構
                                eg. create table t10_b like t1;
                動態分區的數據的加載        
                        要使用動態分區,那必須要開啓動態分區模式,將其設置爲nonstrict                
                        hive>set hive.exec.dynamic.partition=true;
                        hive>set hive.exec.dynamic.partition.mode=nostrict;
                        hive>set hive.exec.max.dynamic.partitions.pernode=1000;        
                        需要注意:前後兩張表字段個數一定要對應
                        insert into table t10_c_d_p partition(dt) select id from t7_partition ;
                        insert into table t10_d_d_p partition(year=2015,school) select id, name, school from t7_partition_1 where year=2015;
                        insert overwrite table t10_d_d_p partition(school, year) select * from t7_partition_1;        
                對同一份數據的多次處理:
                        hive> from sales_log
                        hive> insert into table sales select *  where dt="2015-07-08";
                        hive> insert into table history select * where dt="2015-07-08";
        導出:
                1°、hdfs目錄級別的拷貝:hadoop fs -cp hdfs_uri_1 hdfs_uri_2;
                2°、使用insert overwrite directory命令
                        INSERT OVERWRITE [LOCAL] DIRECTORY '...' SELECT ...FROM...WHERE ...;
                        Export:export tblName to 'hdfs_path';
                                        export table t1 to '/export/';
                        Import:import table from 'hdfs_path'; 
                                        import table t1_1 from "/export/";:

        Hive中hql--->mr
        hql沒有轉化爲mr
                如果說將hql能夠轉化爲hadoop hdfs的shell就不會產生mr。eg select * from tbl[ partition partition_sepc] [limit x];
        hql轉化爲了mr
                hadoop jar xxx.jar input output
Hive中如何控制MR
        Map
                inputSplit/block.size
                hadoop:10M 20M 30M-->3
                hive:10M 20M 30M-->3 CombineHiveInputFormat
                        對小文件進行了合併,減少maptask的數量,提高了map的執行效率
                        10M 20M 100M==130M-->1個,閾值 1.1倍也就是140.8M 
                        1000M/128 = 7
        Reduce
                主要由:hive.exec.reducers.bytes.per.reducer
                        hive.exec.reducers.max以及mapred.reduce.tasks
                 <property>
                        <name>hive.exec.reducers.bytes.per.reducer</name>
                        <value>256000000</value>
                        <description>size per reducer.The default is 256Mb, i.e if the input size is 1G, it will use 4 reducers.</description>
                  </property>
                  <property>
                        <name>hive.exec.reducers.max</name>
                        <value>1009</value>
                        <description>
                          max number of reducers will be used. If the one specified in the configuration parameter mapred.reduce.tasks is
                          negative, Hive will use this one as the max number of reducers when automatically determine number of reducers.
                        </description>
                  </property>
                  hive.exec.parallel並行執行MR
                  hive.exec.parallel.thread.number一次最多執行的job數量
                 
        只有一個Reducer的情況
                進行統計沒有寫group by
                笛卡爾積(A join B on A.xx=B.yy)A:M,B:N M*N
                在我們進行排序的使用order by
        Hive中的排序
                select * from t1 order by id desc;
                order by是一個全局的排序,會產生一個reducer
                sort by是單節點的排序
                        distribute by <col> sort by <col>能夠達到order的效果
                cluster by <col>是對上面distribute by sort by的縮寫 -->不支持asc和desc                

Hive中的join
        inner join 只支持等值連接
        create table if not exists t_class(
           id int comment "班級ID",
           name string comment "班級名稱"
        ) comment "班級表"
        row format delimited
        fields terminated by '\t';
                
        create table if not exists t_student (
                id int comment "學生ID",
                classid int comment "班級ID",
                name string comment "學生名稱",
                birthday date comment "學生出生日期",
                sex int comment "員工性別,1表示男,0表示女",
                phone bigint comment "聯繫電話",
                hometown string comment "籍貫",
                salary float comment "學生薪資"
        ad data local inpath 'student.txt' overwrite into table crxy.t_student;
        ) comment "學員信息表"
        row format delimited
        fields terminated by '\t';
        要求輸出:
        班級,學生姓名,性別(顯示男或女),薪資>14000
        select
                c.name, s.name, if(s.sex == 1, '男', '女') as gender, s.salary
        from t_class c 
        inner join t_student s on c.id = s.classid 
        where s.salary > 14000;

        outer join
                left outer join(會將左表中的滿足條件的數據都查出,右表找不到相應的數據,則會顯示爲NULL)
                        select
                                c.name, s.name, if(s.sex == 1, '男', '女') as gender, s.salary
                        from t_student s 
                        left join t_class c on c.id = s.classid 
                        where s.salary > 14000;
                right outer join        
        大小表join的優化:hive中sql的執行總是從左向右來執行將小表在左邊

        mapjoin
                select /* +MapJOIN(s)*/
                                c.name, s.name, if(s.sex == 1, '男', '女') as gender, s.salary
                        from t_student s 
                        left join t_class c on c.id = s.classid 
                        where s.salary > 14000;
Hive中文件的類型
    <property> 默認爲textfile
        通過 hive-site.xml 配置文件的配置項
        <name>hive.default.fileformat</name>
        <value>TextFile</value>
        <description>
          Expects one of [textfile, sequencefile, rcfile, orc].
          Default file format for CREATE TABLE statement. Users can explicitly override it by CREATE TABLE ... stored as [FORMAT]
        </description>
    </property>
        開啓壓縮:
                set hive.exec.compress.output=true;
                set mapred.output.compress=true;
                set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
                set io.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
                set mapred.output.compression.type=BLOCK;
        TextFile
                Hive 默認格式,數據不做壓縮,磁盤開銷大,數據解析開銷大。
                可結合 Gzip、Bzip2、Snappy 等使用(系統自動檢查,執行查詢時自動解壓),但使用這種方式,
                hive 不會對數據進行切分,從而無法對數據進行並行操作。
        SequenceFile 
                是 Hadoop API 提供的一種二進制文件支持,其具有使用方便、可分割、可壓縮的特點。
                SequenceFile 支持三種壓縮選擇:NONE,RECORD,BLOCK。Record 壓縮率低,一般建議使用 BLOCK 壓縮。
        RCFILE 
                是一種行列存儲相結合的存儲方式。首先,其將數據按行分塊,保證同一個 record 在一個塊上,
                避免讀一個記錄需要讀取多個 block。其次,塊數據列式存儲,有利於數據壓縮和快速的列存取
        Orc 
                文件格式是對 RCFile 的一個擴展和升級,擁有更高效的壓縮比和執行效率。
        Parquet 是新起的一種列式存儲文件類型

        幾種壓縮方式筆記:
        textfile 存儲空間消耗比較大,並且壓縮的 text 無法分割和合並 查詢的效率最低,可以直接存儲,加載數據的速度最高
        sequencefile 存儲空間消耗大,壓縮的文件可以分割和合並 查詢效率高,需要通過text 文件轉化來加載
                 rcfile 存儲空間最小,查詢的效率最高 ,需要通過 text 文件轉化來加載,
                加載的速度最低相比 TEXTFILE 和 SEQUENCEFILE,RCFILE 由於列式存儲方式,數據加載時性能消
                耗較大,但是具有較好的壓縮比和查詢響應。數據倉庫的特點是一次寫入、多次讀取,因此,
                整體來看,RCFILE 相比其餘兩種格式具有較明顯的優勢。
        通過比較:
                使用壓縮可以提高hdfs的存儲能力,還有加快我們查詢效率。
                在工作中常用壓縮方式rc和orc        
        
Hive中的內嵌函數 
                 show functions查看函數
                 desc function functionName;查看相應的函數命令
        case
                select id,
        case id
        when 1 then "TEACHER"
        when 2 then "SALER"
        when 3 then "OFFICER"
        when 4 then "STUDENT"
        else "其他"
        end from dept;

        if: if(expr1, expr2, expr3)==>如果expr1爲真,則返回的結果爲expr2,反之則返回expr3        
        split: split(str, regex)使用regex將str切割爲一個數組
        explode:
                將一個數組返回多行
                [a,b,c]==>
                a
                b
                c
                count
        wordcount例子:
                MR:
                        map:values.toString().split("\t")--->[hello, me]
                        <hello,1>
                        <me,1>--->通過context.write--->reducer[<hello,1>,<hello,1>,<hello,1>]
                        for() {
                                sum+=1;
                        }
                        hello 3
                        me 1                
                hello
                you
                hello
                me
                create table t(line string);
                第一步:進行數據切割
                        select split(line, " ") from t;
                第二步:將第一步的數組轉換成爲多行數據
                        select explode(split(line, " ")) as word from t;
                第三步:對第二步產生的多行數據使用count按照group by進行統計
                        select w.word, count(w.word) count 
                        from (select explode(split(line, " ")) as word from t) w
                        group by w.word;
        hive中行列的轉換
                create table t_u(id int, name string) row format delimited fields terminated by '\t';  
                create table t_a(id int,uid int, address string) row format delimited fields terminated by '\t';
                第一步:兩張表進行多表關聯,查詢出顯示的內容
                        select  u.id, u.name, a.address from t_u u join t_a a on u.id =a.uid;
                第二步:對查詢出的address進行多列轉換
                                需要使用collect_set/collect_list將多行轉換成多列(數組)
                        select
                           u.id, max(u.name) name, collect_set(a.address) addr
                        from t_u u join t_a a on u.id =a.uid 
                        group by u.id;
                第三步:需要將數組中的元素連接成爲字符串:concat_ws
                        select
                           u.id, max(u.name) name, concat_ws(",", collect_set(a.address)) addr
                        from t_u u join t_a a on u.id =a.uid 
                        group by u.id;
                ===>多行數據轉換成多列的值
        多列的數據轉換成多行
                第一步:使用split將多列值轉換成爲一個數組
                        select split(addr, ",") address from t_u_a;
                第二步:使用explode表函數將多列數組轉換成爲多行
                        select explode(split(addr, ",")) address from t_u_a;
                第三步:添加其他查詢字段
                        hive不支持在表函數explode前面直接放置其它查詢字段,爲了滿足業務需求,需要使用lateral view配合explode
                        select id, name, w.address from t_u_a lateral view explode(split(addr, ",")) w as address;
        collect_set
        create table if not exists t_class ( id int comment "班級ID",  name string comment "班級名稱" ) 
              comment "班級表" row format delimited  fields terminated by '\t';

create table if not exists t_student (
    id int comment "學生ID",
    classid int comment "班級ID",
    name string comment "學生名稱",
    birthday date comment "學生出生日期",
    sex int comment "員工性別,1表示男,0表示女",
    phone bigint comment "聯繫電話",
    hometown string comment "籍貫",
    salary float comment "學生薪資"
) comment "學員信息表"
row format delimited
fields terminated by '\t';

load data local inpath 'class.txt' overwrite into table t_class;
load data local inpath 'student.txt' overwrite into table t_student;
        row_number()--分組的排序
                第一步:使用row_number函數進行排序
                        select row_number() over(partition by classid order by salary) rank from t_student;
                第二步:對查詢內容的一個豐富
                        select id, classid, name, if(sex==1, '男','女') as gender, salary, 
                                row_number() over(partition by classid order by salary) rank from t_student
                        where salary is not null;
                第三步:關聯t_class表將classid置換爲具體的部門名稱
                        select s.id, c.name, s.name, if(s.sex==1, '男','女') as gender, s.salary, 
                                row_number() over(partition by s.classid order by s.salary) rank from t_student s
                        join t_class c on s.classid = c.id
                        where salary is not null;                
                升級版:求出組內的TopN
                        select w.* from 
                                (select s.id, c.name, s.name, if(s.sex==1, '男','女') as gender, s.salary, 
                                        row_number() over(partition by s.classid order by s.salary) rank from t_student s
                                join t_class c on s.classid = c.id
                                where salary is not null
                        ) w
                        where w.rank < 3;
hive自定義函數
udf步驟:
        1.寫一個類繼承(org.apache.hadoop.hive.ql.)UDF
        2.覆蓋方法eturn evaluate(param...)
        3.打jar包,提交hive服務器
        4.添加到hive資源裏面(add jar jar的路徑)--->臨時的加入的hive的classpath
        5.創建一個臨時的函數create temparay function functionName as '自定義類的全類名';
        6.執行相應的操作
        7[可選]、drop 臨時函數
        網上有例子:根據生日得到屬性和星座

hive的JDBC
增刪改查

hive權限管理:控制一些人有權限做一些事,一些人沒權限做一些事
        用戶、組、角色
        爲了使用權限管理,需要開啓權限認證:set hive.security.authorization.enabled=true;
        開啓權限認證的時候,我們再創建表的時候,就會提示:No privilege 'Create'等相應權限,
        授予權限:
                grant create on <database|table> <dbName|tblName> to user root;
                查看當前系統用戶:set system:user.name;
                查看當前用戶擁有的權限:show <user|group|role> <uname|gname|rname> on <database|table> <dbName|tblName>;
        組級別的權限
                授予權限:grant select on table t_group to group root;
        角色級別的權限
                如果沒有角色,則需要創建相應的角色:create role roleName;
                將相關的用戶或者添加到角色裏面:grant role roleName to <user|group> <uname|gname>;
                將相關的操作權限賦予給角色:grant <select|create...> on <database|table> <dbName|tblName> to role roleName;
        Hive中有哪些常見的權限:
                ALL------所有的操作
                Create---創建數據庫或表
                DROP-----刪除數據庫或表或分區
                SELECT---查詢表數據
                UPDATE---load
                ALTER----對錶結構的修改
                SHOW_DATABASE---查看數據庫
        剔除權限:
                revoke <create|drop|select|update|...> on <database|table> <dbName|tblName> from <user|group|role> <uname|gname|rname>;
        分區表權限的空
                要做到更細粒度的權限控制,要開啓如下屬性:
                        alter table t_partition set tblproperties("PARTITION_LEVEL_PRIVILEGE"="TRUE");
                爲了能夠操作相關的分區,要對相應的分區進行權限的授予
                        grant <create|drop|select|update|...> on table tblName partition(partition_sepc) to <user|group|role> <uname|gname|rname>;
        Hive中的超級管理員的設置:
                第一步:寫一個類繼承AbstractSemanticAnalyzerHook抽象類
                第二步:覆蓋其中的preAnalyze()或postAnalyze()方法
                                在其中進行當前用戶和超級管理員的權限認證判斷
                                public class HiveHook extends AbstractSemanticAnalyzerHook{
                                        private String admin = "root";
                                        @Override
                                        public ASTNode preAnalyze(HiveSemanticAnalyzerHookContext context,
                                                        ASTNode ast) throws SemanticException {
                                                switch(ast.getToken().getType()) {
                                                case HiveParser.TOK_CREATEDATABASE:
                                                case HiveParser.TOK_CREATETABLE:
                                                case HiveParser.TOK_DROPDATABASE:
                                                case HiveParser.TOK_DROPTABLE:
                                                        if(SessionState.get() != null) {
                                                                String uname = SessionState.get().getAuthenticator().getUserName();
                                                                if(admin.equalsIgnoreCase(uname)) {
                                                                        throw new RuntimeException("不是管理員,不能create|drop");
                                                                }
                                                        }
                                                        break;
                                                default:
                                                        break;
                                                }
                                                return ast;
                                        }
                                }
                第三步:打成jar包,把jar放置到$HIVE_HOME/lib
                第四步:修改hive的配置文件hive-site.xml在hive.semantic.analyzer.hook的value中增加這個類的全類名
                第五步:重啓hive客戶端進行驗證

hive 調優
1.EXPLAIN 
EXPLAIN EXTENDED 
使用EXPLAIN  可以hive對sql的查詢計劃信息解析
        EXPLAIN SELECT COUNT(1) FROM T1;
hive將查詢轉爲mapreduce執行,所以優化hive可以轉化爲優化mr.
根據EXPLAIN展示的信息可以做出優化
2.限制調整,
使用order by;sort by ;distribute by ;cluster by ;limit返回部分結果
3.jvm重用
jvm執行map和reduce任務,啓動jvm過程開銷很大,
開啓jvm重用可以使得jvm實例在同一個job中重用n次,n在配置文件中設置。
4.其他
join優化;小表在左邊
本地模式;並行執行,動態分區,嚴格模式等
hive的調優本質上是對hive-default.xml中參數的優化。

數據傾斜:
shuffle階段優化過程中,會遇到數據傾斜。
如何將map輸出的數據均勻分配到reduce中是解決數據傾斜的根本。

原因:1.key分佈不均勻
     2.業務數據本身的特性
     3.建表時考慮不周全
     4.sql本身就數據傾斜
表現:任務長時間在99%不動。單一reduce的記錄數與平均記錄數差異過大。
解決方案:參數調節,進行負載均衡
hive.map.aggr=true
map端聚合,相當於combiner
hive.groupby.skewindata=true
保證相同的group by key分佈到同一個reduce
sql語句調節
join,map join
業務場景:
日誌中信息丟失,空值產生數據傾斜
1.爲空的字段不參與關聯
2.給空值賦值,io和作業數都少了,空值key賦值字符串加上隨機數
3.日誌信息中不同字段類型關聯產生數據傾斜
例如:當按照用戶id進行兩表join操作時,默認hash操作會按int類型的id進行分配,
這樣string類型的id的記錄都會分配到一個reducer中,
解決辦法將數字類型轉換爲字符串類型
cast(a.user_id as string)

hive面試常見問題
1.Hive內外部表的區別
2.Hive如何做到權限管理
3.Hive的數據傾斜和調優
4.Hive文件壓縮格式有哪些?壓縮效率如何
5.說說對桶表的理解
6.Hive解析hql轉化爲MR的執行過程
7.Hive的分組排序(row_number()),組內TopN
8.hive有哪些保存元數據的方式,有什麼特點
9.hive能見多個庫嗎
10.hive的底層怎麼與數據庫交互的。
11.hive實現統計的查詢語句以及與mr的區別
12.對於hive你寫過哪些UDF函數,作用是幹什麼的
13.hive與hbase的區別
14.hive中的壓縮格式textfile, sequencefile, rcfile, orc的區別
15.hive的工作原理
16.編寫hive自定義函數,實現oracle數據庫中的addmonths函數功能,然後封裝到hive函數庫中。
   Addmonths(data a,int b)求傳入日期a經過b個月後的日期。
17.另外看到一道很不錯的面試題
http://blog.csdn.net/baolibin528/article/details/46774015
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章