創建數據庫
create database mydb;
切換數據庫
use mydb;
創建數據庫
create database if not exists mydb;
創建內部表表的同時加載數據
create table student_test(id INT, info struct<name:STRING, age:INT>) ROW FORMAT DELIMITED FIELDS
TERMINATED BY ',' COLLECTION ITEMS TERMINATED BY ':';
創建外部表
create external table xxx location '/dir';
查看錶信息
describe t1;
查看表的詳細信息
describe extended t1;
刪除數據庫級聯刪除數據庫中的表
DROP DATABASE [IF EXISTED] mydb [CASCADE];
修改列的名稱、類型、位置、註釋
ALTER TABLE t3 CHANGE COLUMN old_name new_name String COMMENT '...' AFTER column2;
增加列
ALTER TABLE t3 ADD COLUMNS (gender int);
從本地文件系統加載數據到表中
load data local inpath '/root/inner_table.dat' into table t1;
從hdfs加載數據到表中
load data inpath '/root/inner_table.dat' into table t1;
創建分區表
create table partition_table(rectime string,msisdn string) partitioned by(province string,city string) row format
delimited fields terminated by '\t' stored as TEXTFILE;
加載數據到分區表
load data local inpath 'files/stu' into table partition_table partition(province='beijing',city='chaoyang');
查看分區
show partitions partition_table;
刪除分區
alter table partition_table drop partition (daytime='2013-02-04',city='bj')元數據,數據文件刪除,但目錄
daytime=2013-02-04還在
桶是更爲細粒度的數據範圍劃分,它能使一些特定的查詢效率更高,比如對於具有相同的桶劃分並且join的列剛好就
是在桶裏的連接查詢,還有就是示例數據,對於一個龐大的數據集我們經常需要拿出來一小部分作爲樣例,然後在樣
例上驗證我們的查詢,優化我們的程序。
桶表是對數據進行哈希取值,然後放到不同文件中存儲。
創建表
create table bucket_table(id string) clustered by(id) sorted by (id) into 4 buckets;插入時先對id取hash值,然後對4取
模分到四個桶中
加載數據
set hive.enforce.bucketing = true;默認是false,啓用桶表必須先設置該變量
insert into table bucket_table select id from stu;
insert overwrite table bucket_table select id from stu;覆蓋原來數據
數據加載到桶表時,會對分桶的字段取hash值,然後與桶的數量取模。把數據放到對應的文件中。
抽樣查詢
select * from bucket_table tablesample(bucket 1 out of 4 on id);
tablesample是抽樣語句,語法:TABLESAMPLE(BUCKET x OUT OF y)
y必須是table總bucket數的倍數或者因子。hive根據y的大小,決定抽樣的比例。例如,table總共分了64份,當y=32
時,抽取 (64/32=)2個bucket的數據,當y=128時,抽取(64/128=)1/2個bucket的數據。x表示從哪個bucket開始抽取。
例 如,table總bucket數爲32,tablesample(bucket 3 out of 16),表示總共抽取(32/16=)2個bucket的數據,分別爲
第3個bucket和第(3+16=)19個bucket的數據。
從文件中裝載數據
hive>LOAD DATA [LOCAL] INPATH '...' [OVERWRITE] INTO TABLE t2 [PARTITION (province='beijing')];
通過查詢表裝載數據
hive>INSERT OVERWRITE TABLE t2 PARTITION (province='beijing') SELECT * FROM xxx WHERE xxx
一次插入多個表
hive>FROM t4
INSERT OVERWRITE TABLE t1 SELECT ...WHERE...
INSERT OVERWRITE TABLE t2 PARTITION (...) SELECT ...WHERE...
INSERT OVERWRITE TABLE t3 PARTITION (...) SELECT ...WHERE...
動態分區裝載數據【動態分區列寫在select子句最後】
hive>set hive.exec.dynamic.partition=true; 啓用動態分區
hive>set hive.exec.dynamic.partition.mode=nostrict; 非嚴格模式
hive>set hive.exec.max.dynamic.partitions.pernode=1000; 最大分區數(目的是限制產生過多文件夾)
hive>INSERT OVERWRITE TABLE t3 PARTITION(province, city)
SELECT t.province, t.city FROM temp t;
如果是嚴格模式,必須指定一個靜態分區,不能全都是動態分區
hive>INSERT OVERWRITE TABLE t3 PARTITION(province='bj', city)
SELECT t.province, t.city FROM temp t WHERE t.province='bj';
導出hive中的數據
可以使用hadoop命令進行文件複製 hdfs dfs -cp source destination
完整建表語句(注意關鍵字順序)
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]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]
[SKEWED BY (col_name, col_name, ...) 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 (...)] ]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)]
[AS select_statement] (Note: not supported when creating external tables.)
hive處理的文件格式
TextFile: 普通文本文件,默認按該類型存儲 不做壓縮,磁盤開銷大,數據解析開銷大
SequenceFile: Hadoop API提供的一種二進制文件支持 可分割、可壓縮 支持三種壓縮選擇:NONE, RECORD,
BLOCK。 Record壓縮率低,一般建議使用BLOCK壓縮
RCFile:是一種行列存儲相結合的存儲方式。首先,其將數據按行分塊,保證同一個record在一個塊上,避免讀一個
記錄需要讀取多個block。其次,block中數據按列式存儲,有利於數據壓縮和快速的列存取。
ORC:
textfile 存儲空間消耗比較大,並且壓縮的text 無法分割和合並 查詢的效率最低,可以直接存儲,加載數據的速度最高
sequencefile 存儲空間消耗最大,壓縮的文件可以分割和合並 查詢效率高,需要通過text文件轉化來加載
rcfile 存儲空間最小,查詢的效率最高 ,需要通過text文件轉化來加載,加載的速度最低
創建表按SequenceFile格式存儲,並設置壓縮形式,最後從其他表插入數據
create table test2(str STRING) STORED AS SEQUENCEFILE;
hive> set hive.exec.compress.output=true;
hive> set mapred.output.compress=true;
hive> set mapred.output.compression.codec=com.hadoop.compression.lzo.LzoCodec;
hive> set io.seqfile.compression.type=BLOCK;
hive> set io.compression.codecs=com.hadoop.compression.lzo.LzoCodec;
hive> INSERT OVERWRITE TABLE test2 SELECT * FROM test1;
創建ORC格式存儲表
hive> create table t1_orc(id int, name string) row format delimited fields terminated by '\t' stored as orc
tblproperties("orc.compress"="ZLIB");
將其他類型的錶轉成ORC格式表
ALTER TABLE ... [PARTITION partition_spec] SET FILEFORMAT ORC
設置默認存儲格式爲ORC
hive> SET hive.default.fileformat=Orc;
hive> insert overwrite table t1_orc select * from t1;
What is a SerDe?
SerDe 是 "Serializer and Deserializer."的縮寫
Hive 使用 SerDe和FileFormat進行行內容的讀寫.
HDFS文件 --> InputFileFormat --> <key, value> --> Deserializer --> 行對象
行對象 --> Serializer --> <key, value> --> OutputFileFormat --> HDFS文件
Hive 使用如下FileFormat 類讀寫 HDFS files:
TextInputFormat/HiveIgnoreKeyTextOutputFormat: 讀寫普通HDFS文本文件.
SequenceFileInputFormat/SequenceFileOutputFormat: 讀寫SequenceFile格式的HDFS文件.
例:
CSV格式的文件也稱爲逗號分隔值(Comma-Separated Values,CSV,有時也稱爲字符分隔值,因爲分隔字符也可
以不是逗號。在本文中的CSV格式的數據就不是簡單的逗號分割的),其文件以純文本形式存儲表格數據(數字和文
本)。CSV文件由任意數目的記錄組成,記錄間以某種換行符分隔;每條記錄由字段組成,字段間的分隔符是其它字
符或字符串,最常見的是逗號或製表符。通常,所有記錄都有完全相同的字段序列。
默認的分隔符是
DEFAULT_ESCAPE_CHARACTER \
DEFAULT_QUOTE_CHARACTER " ---如果沒有,則不需要指定
DEFAULT_SEPARATOR ,
CREATE TABLE csv_table(a string, b string) ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES ( "separatorChar" = "\t",
"quoteChar" = "'", "escapeChar" = "\\") STORED AS TEXTFILE;
紅色部分爲默認,也可以不寫。
該類org.apache.hadoop.hive.serde2.OpenCSVSerde即包含了InputFormat和OutputFormat來處理csv文件。
什麼時候可以避免執行MapReduce?
select * where語句中只有分區字段
set hive.exec.mode.local.auto=true;
group by語句
having語句
order by、sort by、distribute by、cluster by語句
order by是全局排序、sort by是單reduce排序、distribute by是分區字段;
cluster by是distribute by和sort by的簡寫
性能調優
set hive.map.aggr=true;
這個設置可以將頂層的聚合操作放在Map階段執行,從而減輕清洗階段數據傳輸和Reduce階段的執行時間,提升總
體性能。
缺點:該設置會消耗更多的內存。
表連接:
INNER JOIN
表中都有,且兩表符合連接條件
LEFT OUTER JOIN
左表中符合where條件出現,右表可以爲空
RIGHT OUTER JOIN
右表中符合where條件出現,左表可以爲空
FULL OUTER JOIN
LEFT SEMI-JOIN (左半連接)
左表中符合on條件出現,右表不出現
笛卡爾積
是m x n的結果
map-side JOIN
視圖的創建
CREATE VIEW v1 AS select * from t1;
lateral view用於和split, explode等UDTF一起使用,它能夠將一行數據拆成多行數據,在此基礎上可以對拆分後的數
據進行聚合。lateral view首先爲原始表的每行調用UDTF,UTDF會把一行拆分成一或者多行,lateral view再把結果組
合,產生一個支持別名表的虛擬表。
SELECT pageid, adid FROM pageAds LATERAL VIEW explode(adid_list) adTable AS adid;
自定義函數:
1、UDF函數可以直接應用於select語句,對查詢結構做格式化處理後,再輸出內容。
2、編寫UDF函數的時候需要注意一下幾點:
a)自定義UDF需要繼承org.apache.hadoop.hive.ql.UDF。
b)需要實現evaluate函數,evaluate函數支持重載。
4、步驟
a)把程序打包放到目標機器上去;
b)進入hive客戶端,添加jar包:hive>add jar /run/jar/udf_test.jar;
c)創建臨時函數:hive>CREATE TEMPORARY FUNCTION add_example AS 'hive.udf.Add';
d)查詢HQL語句:
SELECT add_example(8, 9) FROM scores;
SELECT add_example(scores.math, scores.art) FROM scores;
SELECT add_example(6, 7, 8, 6.8) FROM scores;
e)銷燬臨時函數:hive> DROP TEMPORARY FUNCTION add_example;
注:UDF只能實現一進一出的操作,如果需要實現多進一出,則需要實現UDAF
使用jdbc訪問hive
首先開啓hive遠程端口
Hive遠程服務啓動#hive --service hiveserver -p 10002 >/dev/null 2>/dev/null &
JAVA客戶端相關代碼
Class.forName("org.apache.hadoop.hive.jdbc.HiveDriver");
Connection con = DriverManager.getConnection("jdbc:hive://192.168.1.102:10000/wlan_dw", "", "");
Statement stmt = con.createStatement();
String querySQL="SELECT * FROM wlan_dw.dim_m order by flux desc limit 10";
ResultSet res = stmt.executeQuery(querySQL);
while (res.next()) {
System.out.println(res.getString(1) +"\t" +res.getLong(2)+"\t" +res.getLong(3)+"\t" +res.getLong(4)+"\t"
+res.getLong(5));
}
JOIN 優化
1.hive對3個或3個以上的表進行join操作時,如果每個on字句都使用相同的連接鍵的話,只會產生一個MapReduce
job。
2.hive會假定查詢中最後一個表示最大的那個表。在對每行記錄進行連接操作時,會將其他表緩存起來,然後掃描最
後那個表進行計算。所以要保證從左到右表的大小是依次增加的。也可以在查詢語句中加入 /*+STREAMTABLE(表名
或別名)*/,指定哪張是最大的表。
3.避免笛卡爾積,select * from a join b where ....。在執行where過濾前首先會對a表和b表進行笛卡爾積,導致過程非
常緩慢,在hive中設置hive.mapred.mode=strict可以阻止笛卡爾積。
4.map-side join 如果連接查詢中只有一張表是小表,可以將小表中的數據放到內存中,在map端就可以進行連接操作
省略了reduce端的過程。需要設置 hive.auto.convert.join=true 並設置小表的大小hive.mapjoin.smalltable.filesize單位
是字節。或在查詢中加入 /*+ MAPJOIN(表名或別名)*/