參考文章:KUDU&Impala基本操作
說明
通過Java client等其他方式在kudu中創建了某個表,要想對該表進行操作,需要在impala中創建外部表,將其映射到impala當中
SQL操作
通過impala對kudu進行sql操作
數據庫操作
--描述表
DESCRIBE tabel_name;
--查看分區情況
SHOW PARTITIONS table_name;
--查看當前使用數據庫
SELECT current_database();
--查看建表語句
SHOW CREATE TABLE table_name
創建數據庫(creat db)
--impala創建數據庫與hive一樣,create database db_name,
--但是這個數據庫只是一個impala端的namespace,
--kudu官網中沒有提到數據庫的概念,猜測可能是沒有這個概念
--impala中創建表的時候比如在test數據庫中創建table_test對應在kudu中爲 test:table_test
--創建數據庫
CREATE DATABASE IF NOT EXISTS POC_TEST;
創建表(creat table)
(0) 創建外部表,內部表
--創建外部表
--假設已經通過Java client等其他方式在kudu中創建了某個表,
--要想對該表進行操作,需要在impala中創建外部表,將其映射到impala當中,例如:
CREATE EXTERNAL TABLE my_mapping_table
STORED AS KUDU
TBLPROPERTIES('kudu.table_name' = 'my_kudu_table');
--創建內部表
--假設要通過impala創建一個新的kudu表,需要在impala中創建一個內部表,例如:
CREATE TABLE testinkudu(…………)
partition by hash partitions 8
STORED AS KUDU [AS SELECT * FROM OTHER_TABLE];
--注:創建內部表時,類似partition by ………stored as kudu的分區聲明語句是必須的。
--無論是 通過client創建的kudu表還是通過impala創建的表,
--都可以在master節點的UI界面的tables選項中查看
Kudu中的分區方法主要有兩種:partition by hash和partition by range
(1) Hash分區
-- 基於hash的分區方法的基本原理是:基於primary key的hash值將每個row劃分到相應的tablet當中,
-- 分區的個數即tablet的個數必須在創建表語句中指定
-- 如果未指定基於某個字段的hash值進行分區,默認以主鍵的hash值進行分區
--主鍵兩個字段,分區字段未指定 hash分區
create table kudu_first_table(
id int,
name string,
age int,
gender string,
primary key(id,name)
)
partition by hash partitions 4
stored as kudu;
--主鍵一個字段,分區字段未指定 hash分區
CREATE TABLE my_first_table
(
id BIGINT,
name STRING,
PRIMARY KEY(id)
)
PARTITION BY HASH PARTITIONS 16
STORED AS KUDU;
--表不存在則創建, 主鍵一個字段, 分區字段未指定 hash分區
CREATE TABLE IF NOT EXISTS POC_TEST.sdc(
id string,
name string,
PRIMARY KEY (id)
)
PARTITION BY HASH(id) PARTITIONS 2
STORED AS KUDU;
TBLPROPERTIES('kudu.master_addresses'='master.msxf.hadoop:7051','kudu.num_tablet_replicas' = '1');
--主鍵兩個字段,分區字段指定,hash分區
create table specify_partition_column(
id int,
name string,
age int,
gender string,
primary key(id,name)
) partition by hash(id) partitions 3
stored as kudu;
--主鍵兩個字段,分區字段指定一個字段,hash分區
create table specify_partition_one_column(
id int,
name string,
age int,
gender string,
primary key(id)
) partition by hash(id) partitions 3
stored as kudu;
--區別:未指定分區字段時,其分區字段默認是主鍵,若主鍵有兩個列則分區字段爲兩個,指定分區字段時,
-- 需要分區列是主鍵的子集;否則會報錯「 Only key columns can be used in PARTITION BY」
--不指定分區:表依然會創建,但是隻有一個分區,會提示「Unpartitioned Kudu tables are ineff
(2) range分區:主要針對時間進行range分區
-- 基於range的分區方法的基本原理是:基於指定主鍵的取值範圍將每個row劃分到相應的tablet當中,
-- 用於range分區的主鍵以及各個取值範圍都必須在建表語句中聲明
CREATE TABLE cust_behavior (
_id BIGINT PRIMARY KEY,
salary STRING,
edu_level INT,
usergender STRING,
`group` STRING,
city STRING,
postcode STRING,
last_purchase_price FLOAT,
last_purchase_date BIGINT,
category STRING,
sku STRING,
rating INT,
fulfilled_date BIGINT
)
PARTITION BY RANGE (_id)
(
PARTITION VALUES < 1439560049342,
PARTITION 1439560049342 <= VALUES < 1439566253755,
PARTITION 1439566253755 <= VALUES < 1439572458168,
PARTITION 1439572458168 <= VALUES < 1439578662581,
PARTITION 1439578662581 <= VALUES < 1439584866994,
PARTITION 1439584866994 <= VALUES < 1439591071407,
PARTITION 1439591071407 <= VALUES
)
STORED AS KUDU;
--優勢:可以根據數據的具體情況建立分區,比如:建立2017年之前的分區,2017-2018,2018-2019,2019-2020,2020-2021,。。。
--劣勢:如果使用單級range分區的話,容易產生數據熱點問題(可混合hash分區使用)、
-- 在range分區中,如果有不止一個字段作爲分區字段的話也可以,語法暫時不清楚;
-- 如果插入一條主鍵的值不落在任何range區間時會插入失敗,並報錯
(3) 混合分區
create table tw_details4(
user_id string,
event_date string,
event string,
properties string,
customer_id int,
project_id int,
primary key(event_date,event,user_id)
) partition by hash(user_id) partitions 3, range(event_date)(
partition values < '2017-01-01',
partition '2017-01-01' <= values < '2018-01-01',
partition '2018-01-01' <= values < '2019-01-01',
partition '2019-01-01' <= values < '2020-01-01',
partition '2020-01-01' <= values < '2021-01-01'
) stored as kudu;
--優勢:可以根據時間進行檢索,來減少需要scan的tablet,插入的時候不會只有一個tabletserver產生熱點
(4) CTAS方式創建表
CREATE TABLE kudu_ti_event_fact_copy
primary key(user_id,event_date)
partition by hash(user_id) partitions 3
stored as kudu
as select user_id,event_date,properties from auto3.ti_event_fact;
刪除表和刪除數據庫
DROP TABLE [表名];
DROP DATABASE [數據庫名];
刪除試圖
DROP VIEW [視圖名];
插入(insert)
impala 允許使用標準 SQL 語句將數據插入 Kudu
--單行插入:
insert into my_first_table(time, uid, event_id, action_value) values(123,"v2", "123", 2)
insert into table1 values(v1,v2,v3)
-- 多行插入:
INSERT INTO my_first_table(time, uid, event_id, action_value) VALUES (1, "john"), (2, "jane"), (3, "jim");
-- 批量插入(Batch Insert)
--從 Impala 和 Kudu 的角度來看,通常表現最好的方法通常是使用 Impala 中的 SELECT FROM 語句導入數據
INSERT INTO my_kudu_table SELECT * FROM legacy_data_import_table;
insert into table1 select v1,v2,v3 from table2;
插入(upsert)
--根據主鍵判定,若已經存在則更新,若不存在則插入
upsert into table1 values(v1,v2,v3)
更新(update)
--單行更新
UPDATE my_first_table SET name="bob" where id = 3;
--批量更新
UPDATE my_first_table SET name="bob" where id > 2;
--where條件後面的column不是主鍵也可以,但是更改的範圍會擴大
--主鍵中不支持更改,只能刪除後重新添加
UPDATE kudu_first_table set age = 32 where id= 2;
UPDATE kudu_first_table set age = 31 where gender= 'female';
查詢操作
--獲取某一天的時間(時間類型轉string類型,在截取時間)
select substr(cast(CREATE_DATE as string),1,10)
from CBEE_ELIST WHERE substr(cast(CREATE_DATE as string),1,10) = '2001-02-01'
刪除(delete)
DELETE FROM my_first_table WHERE id < 3;
更改表
--修改表名,修改的只是表在impala中的映射名
alter table kudu_ti_event_fact_copy rename to kudu_ti_event_fact_copy_rename;
--修改kudu存儲的表名,但是不會改變在impala端的映射表名,也就是在impala中依然訪問更改之前的表名
ALTER TABLE kudu_ti_event_fact_copy_rename
SET TBLPROPERTIES('kudu.table_name' = 'kudu_ti_event_fact_copy');
--修改列屬性
-- --**不支持---
--添加列
alter table kudu_ti_event_fact_copy_rename add columns(method string,time_stamp string);
--刪除列
ALTER table kudu_ti_event_fact_copy_rename drop column method;
--刪除分區
ALTER TABLE range_partition_table DROP RANGE PARTITION VALUES < '2017-01-01';
--添加分區
alter table range_partition_table add range partition values < '2017-01-01';