Hive 的簡單使用及調優參考文檔 html
使用一下命令查看hive的命令行頁面, java
hive --help --service cli 簡化命令爲hive –h linux
會輸出下面的這些東西 sql
-d,--define <key=value> Variable subsitution to apply to hive shell
commands. e.g. -d A=B or --define A=B 數據庫
--database <databasename> Specify the database to use express
-e <quoted-query-string> SQL from command line apache
-f <filename> SQL from files json
-H,--help Print help information 緩存
-h <hostname> connecting to Hive Server on remote host
--hiveconf <property=value> Use value for given property
--hivevar <key=value> Variable subsitution to apply to hive
commands. e.g. --hivevar A=B
-i <filename> Initialization SQL file
-p <port> connecting to Hive Server on port number
-S,--silent Silent mode in interactive shell
-v,--verbose Verbose mode (echo executed SQL to the
console)
咱們經常使用的 hive –e ,hive –f ,hive –S 和hive –h
演示下上面幾個命令的使用示例
假如 但願使用shell腳本把hive庫bdp_3 表裏的mobile_01_2的表數據導出
hive -e "use bdp_3;select * from mobile_01_2;">11.log
就能夠在執行hive命令的當前目錄下看到11.log裏面有表mobile_01_2的數據了。固然爲了切換用戶命令也能夠省略寫成下面的方式,直接在表名前加用戶名
hive -e "select * from bdp_3.mobile_01_2;">12.log
在shell腳本中得到HQL的統計結果 並賦給一個變量
count=`hive -e "select count(*) from bdp_3.mobile_01_2;"`
echo 'count的值爲:'$count
封裝好的hql 命令放到單獨的一個文件裏,而後統一在shell 裏執行,此時可使用hive –f 命令
假設在 /root/shell/11.q 文件下有一句HQL
create table bdp_3.test as
select * from bdp_3.mobile_01_2;
執行命令
hive –f /root/shell/11.q
以後就能在數據庫裏看到這張建立的表了
hive 命令字段補全功能,同linux同樣,敲命令時候敲通常按TAB鍵系統會幫助補全關鍵字,有幾個選擇的時候會給提示
在hive CLI窗口 輸入! 加分號結尾就能使用shell 命令了,好比查看當前目錄
顯示當前目錄文件
這個功能和真正的shell仍是有寫區別的,能夠本身多試試
只須要把hadoop 命令中的關鍵字hadoop 幹掉,分號結尾就行了,好比,查看hdfs 根目錄 hadoop 命令爲 hadoop dfs –ls / 在hive中只須要敲dfs –ls /
hive 數據導出有三種常見的場景
(1)導出到本地文件系統;(2)導出到HDFS中;(3)導出到Hive的另外一個表中。
insert overwrite local directory '/root/shell/mobile_01_1'
select * from mobile_log_01;
這條HQL的執行須要啓用Mapreduce完成,運行完這條語句以後,將會在本地文件系統的/root/shell/mobile_01_1目錄下生成文件,這個文件是Reduce產生的結果(這裏生成的文件名是000000_0),咱們能夠看看這個文件的內容
注:上面使用的都是默認的導出格式,若是須要使用特定的分隔符導出可使用下面的語句
insert overwrite local directory '/root/shell/mobile_01_3'
row format delimited
fields terminated by '$'
select * from bdp_3.mobile_01_1;
insert overwrite directory '/root/shell/mobile_01_1'
select * from mobile_log_01;
導出本地和導出到hdfs的區別 就差一個local關鍵字
Hive 還可使用hive –e 和hive –f 命令來導出數據如同我前面1.1.1同樣,我這裏就不在講述
這個同常見的sql命令同樣,我就不在講述
hive> create database if not exists db_test;
OK
Time taken: 2.3 seconds
hive> show databases;
OK
bdp
bdp_3
db_test
default
Time taken: 0.526 seconds, Fetched: 4 row(s)
hive> show databases like 'db*';
OK
db_test
Time taken: 0.075 seconds, Fetched: 1 row(s)
使用 use 命令切換不一樣的數據庫
use bdp_3;
Hive建表我這裏很少說了,比較基礎,給幾個查看錶的語句
查看數據庫下面的表
hive> show tables;
hive> show tables in bdp_3;
hive> describe extended bdp_3.mobile_01_1;
hive>show partitions mobile_01_1;
CREATE TABLE BOSS_05016_HD2
(
feild_1 STRING,
feild_2 STRING,
feild_3 STRING,
feild_4 STRING,
feild_5 STRING,
feild_6 STRING,
feild_7 STRING)
ROW format delimited
fields terminated by'\t' --指定製表符爲列分隔符
lines terminated by'\n' --指定換行符爲行分隔符(注:目前hive好像只支持換行符爲行分隔符,默認也是這樣,能夠不指定)
;
hive>drop table if exists mobile_01_1;
hive> alter table mobile_01_1 rename to mobile_01_3;
大多數表能夠經過alter table 語句來修改 可是這隻會修改表的元數據,表數據自己不會有任何修改
Hive 能夠修改表名,表字段名,修改列,增長或者刪除列,也能夠經過alter table 來刪除和添加分區表的分區
這裏後續慢慢補充
可使用下面命令來查看hive目前支撐的內部函數
hive> show functions;
OK
!
!=
%
&
*
+
-
/
<
<=
<=>
<>
=
==
>
>=
^
abs
acos
and
array
array_contains
ascii
asin
assert_true
atan
avg
base64
between
bin
case
ceil
ceiling
coalesce
collect_set
compute_stats
concat
concat_ws
context_ngrams
conv
corr
cos
count
covar_pop
covar_samp
create_union
cume_dist
date_add
date_sub
datediff
day
dayofmonth
decode
degrees
dense_rank
div
e
elt
encode
ewah_bitmap
ewah_bitmap_and
ewah_bitmap_empty
ewah_bitmap_or
exp
explode
field
find_in_set
first_value
floor
format_number
from_unixtime
from_utc_timestamp
get_json_object
hash
hex
histogram_numeric
hour
if
in
in_file
index
inline
instr
isnotnull
isnull
java_method
json_tuple
lag
last_value
lcase
lead
length
like
ln
locate
log
log10
log2
lower
lpad
ltrim
map
map_keys
map_values
max
min
minute
month
named_struct
negative
ngrams
noop
noopwithmap
not
ntile
nvl
or
parse_url
parse_url_tuple
percent_rank
percentile
percentile_approx
pi
pmod
positive
pow
power
printf
radians
rand
rank
reflect
reflect2
regexp
regexp_extract
regexp_replace
repeat
reverse
rlike
round
row_number
rpad
rtrim
second
sentences
sign
sin
size
sort_array
space
split
sqrt
stack
std
stddev
stddev_pop
stddev_samp
str_to_map
struct
substr
substring
sum
tan
to_date
to_unix_timestamp
to_utc_timestamp
translate
trim
ucase
unbase64
unhex
unix_timestamp
upper
var_pop
var_samp
variance
weekofyear
when
windowingtablefunction
xpath
xpath_boolean
xpath_double
xpath_float
xpath_int
xpath_long
xpath_number
xpath_short
xpath_string
year
|
~
Time taken: 0.106 seconds, Fetched: 191 row(s)
hive>
附件爲hive函數大全
Hive 支持一般的SQL JOIN 語句,可是隻支持等值鏈接
分析一個語句
Select * from
table_1 a join table_2 b on a.serv_id = b.serv_id
join table_3 c on a.serv_id = c.serv_id
HIVE的解析執行順序是按照從左到右,hive對每一個join對象啓動一個mapreduce任務,首先對 表a和表b進行鏈接操做 而後將輸出結果和表c進行鏈接操做。
因此咱們能夠經過合理的指定鏈接表的順序來優化語句,保證查詢順序中表的大小從左到右依次是增長的。Hive執行時假定查詢中最後一個表是最大的表,在對每行記錄進行鏈接操做時,它會先嚐試將其餘表緩存起來,而後掃描最後那個表進行計算。
Select /*+STREAMTABLE(a) */ * from
table_1 a join table_2 b on a.serv_id = b.serv_id
join table_3 c on a.serv_id = c.serv_id;
經過這個標記來告訴hive 那張表是大表,hive在執行時會嘗試將a表做爲驅動表。
若是全部的表中有一張是小表,能夠在最大的表經過mapper的時候將小表徹底放到內存中,hive能夠在map端執行鏈接過程,由於hive能夠和內存中的小表進行逐一匹配,從而省略掉常規鏈接所須要的reduce過程。
詳細解讀能夠查看
http://tech.ddvip.com/2013-10/1381313795203738.html
hive v0.7版本之前 使用這個優化能夠這麼寫語句
select /*MAPJOIN(d) */ s.ymd,s.symbol,d.dividend from
stocks s join dividends s on s.ymd=d.ymd;
hive v0.7版本之後,廢棄這個標記方式,(增長這個標記一樣有用),需設置hive的屬性,hive.auto.convert.JOIN的值爲true,默認這個屬性的值是false。
用戶能夠設置使用這個優化的小表的大小
hive.mapjoin.smalltable.filesize=25000000 (默認是25M)
注意:hive的right out join 和full out join 不支持這個優化
學習hive是如何工做的,第一個步驟就是學習explain 功能,能夠幫助咱們學習hive是如何將查詢
explain select * from boss_05002;
explain select count(1) from boss_05002;
hive> explain select count(1) from boss_05002;
OK
ABSTRACT SYNTAX TREE:
(TOK_QUERY (TOK_FROM (TOK_TABREF (TOK_TABNAME boss_05002))) (TOK_INSERT (TOK_DESTINATION (TOK_DIR TOK_TMP_FILE)) (TOK_SELECT (TOK_SELEXPR (TOK_FUNCTION count 1)))))
STAGE DEPENDENCIES:
Stage-1 is a root stage
Stage-0 is a root stage
STAGE PLANS:
Stage: Stage-1
Map Reduce
Alias -> Map Operator Tree:
boss_05002
TableScan
alias: boss_05002
Select Operator
Group By Operator
aggregations:
expr: count(1)
bucketGroup: false
mode: hash
outputColumnNames: _col0
Reduce Output Operator
sort order:
tag: -1
value expressions:
expr: _col0
type: bigint
Reduce Operator Tree:
Group By Operator
aggregations:
expr: count(VALUE._col0)
bucketGroup: false
mode: mergepartial
outputColumnNames: _col0
Select Operator
expressions:
expr: _col0
type: bigint
outputColumnNames: _col0
File Output Operator
compressed: false
GlobalTableId: 0
table:
input format: org.apache.hadoop.mapred.TextInputFormat
output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
Stage: Stage-0
Fetch Operator
limit: -1
Time taken: 0.314 seconds, Fetched: 52 row(s)
Limit 語句是你們常常用到的,可是不少狀況下limit語句仍是須要執行這個查詢語句,而後返回部分結果,由於這種狀況一般是浪費的,因此應該儘量避免出現這種狀況
Hive 有個配置屬性能夠開啓:
hive.limit.optimize.enable
當hive.limit.optimize.enable=true時,有兩個對應的參數能夠設置
hive.limit.optimize.limit.file和hive.limit.row.max.size
注意:這個功能有一個缺陷 ,有可能輸入中有用的數據永遠不會被處理到,任意一個須要reduce步驟的查詢,join和group by操做 以及聚合函數的調用,都會產生不一樣的結果。
大多數的hadoop job 是須要hadoop提供的可擴展性來處理大數據的,不過,有時hive的輸入數據量是很是小的,在這種狀況下,爲查詢觸發執行任務的時間消耗可能會比實際job的執行時間要多的多,對於大多數這種狀況,hive能夠經過本地模式在單臺機器上處理全部的任務,對於小數據集執行的時間能夠明顯縮短:
用戶能夠設置hive屬性:hive.exec.mode.local.auto = true 來讓hive 在適當的時候自動啓動這個優化
Hive 會將一個查詢轉化成一個或多個階段,這樣的階段能夠是mapreduce階段,抽樣階段,合併階段,limit階段,或者hive執行過程當中可能須要的其餘階段,默認狀況下hive一次性只會執行一個階段,不過某個特定的job可能包含衆多階段,而這些階段可能並不是徹底互相依賴,也就是說這些階段是能夠並行的,這樣能夠縮短整個job的執行時間縮短。
能夠經過設置hive參數 hive.exec.parallel=true 來開啓併發執行。
Hive經過將查詢劃分紅一個或多個mapreduce任務來達到並行的目的,每一個任務均可能具備多個mapper和reducer任務,肯定最佳的mapper個數和reducer 個數取決於多個變量,例如輸入數據量大小以及對這些數據執行的操做類型等。
通常,hive是按照輸入的數據量大小來肯定reducer 個數的,咱們能夠經過dfs –count命令來計算輸入量大小。能夠經過屬性 hive.exec.reducers.bytes.per.reducers.bytes.per.reducer來設置。默認值是1GB。Hive默認的reducer個數是3。能夠經過設置屬性mapred.reduce.tasks的值來設置。
在共享集羣上處理大任務時,集羣能夠提供的map和reduce 資源個數是固定的,某個大job可能會消耗完全部的資源二致使其餘job沒法執行,能夠經過設置hive.exec.reducers.max屬性來限制某個查詢消耗太多的reducer資源。
JVM重用是hadoop調優參數的內容,其對hive的性能具備很是大的影響,特別是對於很難避免小文件的場景或task特別多的場景,這類場景大多數執行時間很短。
Hadoop 的默認配置一般是使用派生JVM來執行map和reduce任務的,這是JVM的啓動過程可能會形成至關大的開銷,尤爲是執行的job包含成百上千個task任務的狀況下JVM可使的JVM實例在同一個job中從新使用N次。N的值能夠在hadoop的mapred-site.xml文件中進行設置。
注意: 這個功能的缺點,開啓JVM重用會一直佔用使用到的task插槽,以便進行重用,直到任務完成後才釋放,若是某個job中 有幾個reduce task 執行的時間要比其餘的reduce task 消耗的時間多的多的話,那麼保留的插槽會一直空閒,直到全部task都結束了才釋放。
索引能夠用來加快含有group 不要 語句的查詢計算速度。Hive 從 v0.8.0開始增長了一個bitmap 索引實現
Hive不要求將數據轉換成特定的格式才能使用。壓縮一般會節約客觀的磁盤空間。壓縮一樣能夠增長吞吐量和性能。
hive> set io.compression.codecs;
io.compression.codecs=org.apache.hadoop.io.compress.DefaultCodec,
org.apache.hadoop.io.compress.GzipCodec,
org.apache.hadoop.io.compress.BZip2Codec,
org.apache.hadoop.io.compress.DeflateCodec,
org.apache.hadoop.io.compress.SnappyCodec,
org.apache.hadoop.io.compress.Lz4Codec
hive>
BZip2壓縮率最高,可是同時消耗 最多的cpu,GZip是壓縮率和解壓縮速度上的下一個選擇。 在須要優先考慮磁盤空間利用率和I/O的狀況下,能夠優先考慮這兩種壓縮方式。
LZO和Snappy 壓縮率比前面兩種小,可是 壓縮解壓速度要快,特別是解壓縮過程,若是相對於磁盤空間和I/O開銷,頻繁的讀取數據所需的解壓縮速度更重要的話,能夠優先考慮這兩種方式。
另外一個重點考慮的因素是壓縮文件是否可分割。
Mapreduce 須要將很是大的輸入文件分割成多個劃分(一般一個文件一個劃分),每一個劃分會被分發到單獨的map進程中,文本文件每一行一條記錄,hadoop知道文件的記錄邊界。GZip和Snappy 將這些邊界信息掩蓋了,BZip2和LZO提供了塊級別的壓縮,每一個塊含有完整的記錄信息,hadoop能夠在塊級別對這些文件進行劃分。
對中間數據進行壓縮能夠減小job中map和reduce task 間的數據傳輸。對於中間數據壓縮,選擇一個低cpu開銷的編解碼器比較合理,推薦使用Snappycodec。能夠經過設置屬性:hive.exec.compress.intermediate=true來開啓中間件壓縮。
Hive 建立內部表時,會將數據移動到數據倉庫指向的路徑;若建立外部表,僅記錄數據所在的路徑, 不對數據的位置作任何改變。在刪除表的時候,內部表的元數據和數據會被一塊兒刪除,而外部表只刪除元數據,不刪除數據。這樣外部表相對來講更加安全些,數據組織也更加靈活,方便共享源數據。
Hive 有一個參數能夠用來控制hive是否爲嚴格模式hive.mapred.mod=strict,當處於嚴格模式下有不少操做是不容許的,好比,不加limit 的全表查詢,表的笛卡爾積 join 操做,分區表不加分區過濾的查詢 ,orderby不加limit的查詢
可參考:http://blog.csdn.net/wisgood/article/details/19852553
Hive的分區字段是用來劃分文件目錄的,自己不須要在數據文件中存在
假設stocks表 的分區字段爲symbol 執行以下查詢
Select count(distinct symbol) from stocks 會返回結果 0 這個是hive存在的bug
假設 有張employees 表的taxes 字段是float 類型的,標識有兩條數據的taxes 的值爲0.2
此時使用查詢
Select * from employees where taxes > 0.2;
你會驚奇的發現 這兩條數據在列!!
爲了不這種狀況發生應該使用下列語句
Select * from employees where taxes > cast(0.2 as float);