1. 程式人生 > >hive學習筆記之-資料定義

hive學習筆記之-資料定義

1. 資料庫定義及操作

--建立資料庫

hive(default)> SET hive.cli.print.current.db=false;

hive> CREATE DATABASE financials;

--建立庫時加判斷語句

hive> CREATE DATABASE if not exists financials;

--也可以使用關鍵字schames 代替database,是一樣的

hive> CREATE SCHEMA if not exists financials;

--檢視資料庫

hive> SHOW DATABASE;

default

financials

hive> SHOW DATABASES LIKE 'fin*';

financials

--指定資料建立目錄

hive> CREATE DATABASE financials1     

> LOCATION '/user/hive/warehouse/';

--檢視資料描述

hive> DESC DATABASE financials1;

financials1             hdfs://nticket1:9000/user/hive/warehouse

Time taken:0.043 seconds, Fetched: 1 row(s)

--指定自定義key-value引數建立資料庫及檢視

hive> drop database if exists financials;

hive> CREATE DATABASE financials

    > WITH DBPROPERTIES ('creator' = 'licz','date' = '2014-01-23');

hive> DESC DATABASE financials;

financials             hdfs://nticket1:9000/user/hive/warehouse/financials.db

hive> DESC DATABASE EXTENDED financials ;

financials             hdfs://nticket1:9000/user/hive/warehouse/financials.db  {date=2014-01-23,creator=licz}

--切換資料庫

hive> USE financials1;

hive雖然沒有像mysql那樣有檢視當前資料庫的命令,但可以通過hive.cli.print.current.db引數達到同樣的目的。

mysql> select database();

+------------+

| database() |

+------------+

| mysql      |

+------------+

1 row in set(0.00 sec)

hive> set hive.cli.print.current.db=true;

hive(financials1)> use financials;

hive(financials)>

--刪除資料庫

hive> DROP DATABASE financials;

hive> DROP DATABASE IF EXISTS financials;

如果資料庫下面有表存在,要刪除表之後再用上面的語句,否則加cascade子句

hive> DROP DATABASE IF EXISTS financials CASCADE;

2. 修改資料庫

hive (financials)>alter database financials set dbproperties ('creator' = 'lichangzai','editedby' = 'licz' ); 

hive(financials)> desc database extended financials;

financials             hdfs://nticket1:9000/user/hive/warehouse/financials.db  {edited by=licz, date=2014-01-23,creator=lichangzai}

3. 建立表

下面是一個建表的例子:

hive > create database mydb;

hive >

CREATE TABLE IF NOT EXISTS mydb.employees (

name        STRING COMMENT 'Employee name',

salary        FLOAT  COMMENT'Employee salary',

subordinates    ARRAY<STRING> COMMENT 'Names of subordinates',

deductions    MAP<STRING, FLOAT>

COMMENT 'Keys are deductions names, values are percentages',

address       STRUCT<street:STRING,city:STRING, state:STRING, zip:INT>

COMMENT 'Home address')

COMMENT 'Description ofthe table'

LOCATION '/user/hive/warehouse/mydb.db/employees'

TBLPROPERTIES ('creator'='li','created_at'='2014-1-23 10:00:00');

根據上節的建表語句,上面例子增加了些附加子句

--建立和其它表相同結構的表

CREATE TABLE IFNOT EXISTS mydb.employees2

LIKEmydb.employees;

--檢視詳細表

hive > descextended mydb.employees;

4. 管理表

Hive中分管理表和外部表,管理表又叫託管表、內部表。

以上建立的表都是管理表,可以表裡的資料進行直接操作,刪除表後表的內容也被告刪除。

5. 外部表

下面是一個例子說明外部表的用法。

--檢視外部檔案

[[email protected]~]$ hadoop dfs -ls /data/stocks

Found 3 items

-rw-r--r--   2 licz supergroup       8645 2014-01-24 14:17/data/stocks/sz000001.txt

-rw-r--r--   2 licz supergroup       8368 2014-01-24 14:17/data/stocks/sz000002.txt

-rw-r--r--   2 licz supergroup       7720 2014-01-24 14:17/data/stocks/sz000003.txt

目錄下3個檔案,每個檔案中有100條記錄

內容如下:

[[email protected]~]$ hadoop dfs -cat /data/stocks/sz000001.txt|head -5

sz,10000001,2013-07-0800:00:00,1983.215,1983.215,1953.121,1958.273,84136491,2007.199

sz,10000001,2013-07-0500:00:00,2006.191,2021.541,2002.367,2007.199,91345222,2006.098

sz,10000001,2013-07-0400:00:00,1982.870,2022.136,1974.103,2006.098,100394183,1994.268

sz,10000001,2013-07-0300:00:00,1996.506,1996.537,1965.519,1994.268,93466471,2006.560

sz,10000001,2013-07-0200:00:00,1992.890,2007.620,1978.428,2006.560,86415418,1995.242

--建立外部表

CREATE EXTERNAL TABLE IF NOT EXISTS stocks (

exchange STRING,

symbol STRING,

ymd STRING,

price_open FLOAT,

price_high FLOAT,

price_low FLOAT,

price_close  FLOAT,

volume INT,

price_adj_close FLOAT)

ROW FORMAT DELIMITED 

FIELDS TERMINATED BY ','

LOCATION'/data/stocks';

--檢視外部表記錄

hive (mydb)>select * from stocks limit 10;

OK

sz      10000001        2013-07-08 00:00:00     1983.215        1983.215        1953.121        1958.273        84136491        2007.199

sz      10000001        2013-07-05 00:00:00     2006.191        2021.541        2002.367        2007.199        91345222        2006.098

sz      10000001        2013-07-04 00:00:00     1982.87 2022.136        1974.103        2006.098        100394183       1994.268

sz      10000001        2013-07-03 00:00:00     1996.506        1996.537        1965.519        1994.268        93466471        2006.56

hive (mydb)>select count(*) from stocks; 

300

--建立結構相同的空表

和管理表一樣,外部表也能用like建立和其它表管理表一樣的空表

CREATE EXTERNAL TABLE IF NOT EXISTS mydb.employees3

LIKEmydb.employees

LOCATION'/path/to/data';

6. 分割槽表

分割槽管理表

--建立分割槽表

DROP TABLE IFEXISTS employees;

CREATE TABLE employees (

name STRING,

salary FLOAT,

subordinates ARRAY<STRING>,

deductions MAP<STRING, FLOAT>,

address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>

)

PARTITIONED BY(country STRING, state STRING)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY ','

COLLECTION ITEMS TERMINATED BY '|'

MAP KEYS TERMINATED BY ':';

hive (mydb)>desc employees;

OK

name                    string                  None               

salary                  float                   None               

subordinates            array<string>           None                

deductions              map<string,float>       None               

address                struct<street:string,city:string,state:string,zip:int>  None               

country                 string                  None               

state                   string                  None               

# PartitionInformation         

# col_name              data_type               comment            

country                 string                  None                

state                   string                  None               

Time taken:0.129 seconds, Fetched: 13 row(s)

--匯入資料

load data local inpath '/app/hadoop/data/employees_1'

overwrite into table employees partition(country = 'CH',state = 'BeiJin');

load data local inpath '/app/hadoop/data/employees_2'

overwrite into table employees partition(country = 'US',state = 'NY');

--匯入後目錄結構

.../employees/country=CH/state=BeiJin'

.../employees/country=US/state=NY

.../employees/country=US/state=AK

--查看錶的分割槽

hive (mydb)>show partitions employees;                                              

OK

country=US/state=CL

country=US/state=NY

country=CH/state=BeiJin

hive> SHOWPARTITIONS employees PARTITION(country='US');

country=US/state=AL

country=US/state=AK

...

注意:

當用戶不加限制條件對一個非常大的分割槽表進行全表掃描時,這樣觸發一個巨大的MapReduce Job,會給硬碟帶來很大的壓力。所以Hive強烈建議使用“strict”,即當用戶的查詢語句不加where條件時,是禁止對分割槽表進行查詢的。你能改成“nonstrict”模式(預設的模式)取消這種限制。

hive (mydb)>set hive.mapred.mode=strict;

hive (mydb)>select * from employees;   

FAILED: SemanticException[Error 10041]: No partition predicate found for Alias "employees"Table "employees"

外部分割槽表:

一個分割槽表例項:

CREATE EXTERNAL TABLE IF NOT EXISTS log_messages (

hms INT,

severity STRING,

server STRING,

process_id INT,

message STRING)

PARTITIONED BY(year INT, month INT, day INT)

ROW FORMATDELIMITED FIELDS TERMINATED BY '\t';

上面建立外部表語句可以看到,我們沒有加像非分割槽表那樣的LOCATION子句。

外部分割槽表在建立時是不需要加LOCATION子句的,代替的是通過ALTER TABLE語句新增各自的分割槽。如下:

--新增外部表的分割槽

ALTER TABLE log_messages ADD PARTITION(year = 2012, month = 1, day = 2)

LOCATION 'hdfs://master_server/data/log_messages/2012/01/02';

7. 刪除表

DROP TABLE IFEXISTS employees;

如果啟用hadoop回收站(.Trash)功能,刪除的會移動到.Trash目錄,通過設定fs.trash.interval引數回收站的回收週期。但不是能保證所有版本的都能使用這咱方法。如果不小刪除了重要的管理表,可以重新建立一個相同表名的空表,然後把回收站的移回原來的目錄,這樣就能恢復資料。

8. 修改分割槽表

--重新命名

ALTER TABLE log_messages RENAME TO logmsgs;

--新增外部分割槽表分割槽

ALTER TABLE log_messages ADD IF NOT EXISTS

PARTITION (year= 2011, month = 1, day = 1) LOCATION '/logs/2011/01/01'

PARTITION (year= 2011, month = 1, day = 2) LOCATION '/logs/2011/01/02'

PARTITION (year= 2011, month = 1, day = 3) LOCATION '/logs/2011/01/03'

...;

注意:當新增單個分割槽時,分割槽目錄會動建立,但如果同時新增多個分割槽時,只會建立第一個分割槽的目錄。如上面的語句,只會建立/logs/2011/01/01目錄,其它兩個不會建立。


--改變分割槽的位置

ALTER TABLE log_messages PARTITION(year = 2011, month = 12, day = 2)

SET LOCATION 's3n://ourbucket/logs/2011/01/02';

--刪除分割槽

ALTER TABLE log_messages DROP IF EXISTS PARTITION(year = 2011, month = 12, day = 2);

9. 列的修改

--修改列的名字並改變列的位置

ALTER TABLE log_messages

CHANGE COLUMN hms hours_minutes_seconds INT

COMMENT 'Thehours, minutes, and seconds part of the timestamp'

AFTER severity;

上面的語句作用是,修改hms列的名字為hours_minutes_seconds,並把它放在severity列之後。

改之前:


改之後:

--新增列

ALTER TABLE log_messages ADD COLUMNS (

app_name  STRING COMMENT 'Application name',

session_id STRING  COMMENT 'The current sessionid');

--替換列

ALTER TABLE log_messages REPLACE COLUMNS (

hours_mins_secs INT  COMMENT 'hour, minute, seconds fromtimestamp',

severity  STRING COMMENT 'The message severity'

message  STRING COMMENT 'The rest of the message');

上面的語句是重新命名原來的hms列為hours_mins_secs,刪除掉原來的server和process_id列。

但注意REPLACE語句只有在本地的SerDe 模式的表上使用,後面的章節會提到。

--修改表的屬性測試報錯

ALTER TABLE log_messages SET TBLPROPERTIES

('notes' = The process idis no longer captured; this column is always NULL');

--修改儲存屬性

ALTER TABLE log_messages

PARTITION(year =2011, month = 1, day = 1)

SET FILEFORMAT SEQUENCEFILE;

ALTER TABLE stocks

CLUSTERED BY(exchange, symbol)

SORTED BY(symbol)

INTO 48 BUCKETS;

10 .其它修改表語句

--鉤回語句

ALTER TABLE log_messages TOUCH

PARTITION (year =2012, month = 1, day = 1);

執行上面的語句後,當hive的外部檔案被修改時,會觸發一個鉤回操作

--歸檔分割槽語句

ALTER TABLE log_messages ARCHIVE

PARTITION(year =2012, month = 1, day = 1);

歸檔分割槽僅是減少檔案系統檔案的數量,減少namenode的壓力,不會減少空間使用。反操作語句是NOARCHIVE

--保護分割槽不會被刪除

ALTER TABLE log_messages

PARTITION(year =2012, month = 1, day = 1) ENABLE NO_DROP;

hive (mydb)>ALTER TABLE logmsgs

           > PARTITION(year = 2014, month =1, day = 21) ENABLE NO_DROP;

hive (mydb)>ALTER TABLE logmsgs DROP IF EXISTS PARTITION(year = 2014, month = 1, day = 21);

FAILED:SemanticException [Error 30011]: Partition protected from being [email protected]@year=2014/month=1/day=21

hive (mydb)>ALTER TABLE logmsgs

           > PARTITION(year = 2014, month =1, day = 21) disABLE NO_DROP;

OK

Time taken: 0.25seconds

hive (mydb)>ALTER TABLE logmsgs DROP IF EXISTS PARTITION(year = 2014, month = 1, day = 21);

Dropping thepartition year=2014/month=1/day=21

OK

Time taken:0.429 seconds

hive (mydb)>show partitions logmsgs;

OK

year=2014/month=1/day=20

year=2014/month=1/day=22

Time taken:0.105 seconds, Fetched: 2 row(s)

--保護分割槽不能被查詢

ALTER TABLE log_messages

PARTITION(year =2012, month = 1, day = 1) ENABLE OFFLINE;