倫 大淘寶技術 2024年07月08日 18:03 浙江
本文旨在收集整理ODPS開發(fā)中入門及進階級知識,盡可能涵蓋大多ODPS開發(fā)問題,成為一本mini百科全書,后續(xù)也會持續(xù)更新。希望通過筆者的梳理和理解,幫助剛接觸ODPS開發(fā)的同學快速上手。
本文為該系列第一篇:入門篇。
筆者不才,有任何錯誤紕漏,歡迎大家指正。
基礎功能介紹
一般來說,數(shù)據(jù)開發(fā)包括了以下幾個類型:
在此,我們重點介紹一下其中MaxCompute模塊(MaxCompute是適用于數(shù)據(jù)分析場景的企業(yè)級SaaS模式云數(shù)據(jù)倉庫)的功能:
基礎SQL
具體語句1:
--創(chuàng)建新表。
create [external] table [if not exists] <table_name>
[primary key (<pk_col_name>, <pk_col_name2>),(<col_name> <data_type>
[not null] [default <default_value>] [comment <col_comment>], ...)]
[comment <table_comment>]
[partitioned by (<col_name> <data_type> [comment <col_comment>], ...)]
--用于創(chuàng)建聚簇表時設置表的Shuffle和Sort屬性。
[clustered by | range clustered by (<col_name> [, <col_name>, ...])
[sorted by (<col_name> [asc | desc] [, <col_name> [asc | desc] ...])] into <number_of_buckets> buckets]
--僅限外部表。
[stored by StorageHandler]
--僅限外部表。
[with serdeproperties (options)]
--僅限外部表。
[location <osslocation>]
--指定表為Transactional1.0表,后續(xù)可以對該表執(zhí)行更新或刪除表數(shù)據(jù)操作,但是Transactional表有部分使用限制,請根據(jù)需求創(chuàng)建。
[tblproperties("transactional"="true")]
--指定表為Transactional2.0表,后續(xù)可以做upsert,增量查詢,time-travel等操作
[tblproperties ("transactional"="true" [, "write.bucket.num"="N", "acid.data.retain.hours"="hours"...])] [lifecycle <days>]
;
-------------------------------------------------------------------
--例子:
CREATE TABLE IF NOT EXISTS xxx.xxxx_xxxx_xxxx_hh
(
xxxxx STRING COMMENT '商品'
,xxxxx STRING COMMENT '名字'
)
COMMENT 'xxx表'
PARTITIONED BY
(
ds STRING COMMENT 'yyyymmddhh'
)
LIFECYCLE 7
;
參數(shù)說明:
external:可選。表示創(chuàng)建的表為外部表。
if not exists:可選。如果不指定if not exists選項而存在同名表,會報錯。
table_name:必填。表名。
primary key(pk):可選。表的主鍵。
col_name:可選,表的列名。
col_comment:可選。列的注釋內(nèi)容。
data_type:可選。列的數(shù)據(jù)類型。
not null:可選。禁止該列的值為NULL。default_value:可選。指定列的默認值。
table_comment:可選。表注釋內(nèi)容。
lifecycle:可選。表的生命周期。
partitioned by (<col_name> <data_type> [comment <col_comment>], ...:可選。指定分區(qū)表的分區(qū)字段。
具體語句2:修改表的所有人
alter table <table_name> changeowner to <new_owner>;
--------------------------------------------------------
--例子
--將表test1的所有人修改為ALIYUN$xxx@aliyun.com
alter table test1 changeowner to 'ALIYUN$xxx@aliyun.com';
--將表test1的所有人修改為名稱為ram_test的RAM用戶
alter table test1 changeowner to 'RAM$13xxxxxxxxxxx:ram_test';
參數(shù)說明:
table_name:必填。待修改Owner的表名。
new_owner:必填。修改后的Owner賬號。如果要修改Owner為RAM用戶,格式為:RAM$<UID>:<ram_name>,其中UID為阿里云賬號的賬號ID,ram_name為RAM用戶顯示名稱。
具體語句3:修改表的注釋
alter table <table_name> set comment '<new_comment>';
--------------------------------------------------------
--例子
alter table sale_detail set comment 'new coments for table sale_detail';
參數(shù)說明:
table_name:必填。待修改注釋的表的名稱。
new_comment:必填。修改后的注釋名稱。
具體語句4:修改表的修改時間
alter table <table_name> touch;
--------------------------------------------------------
--例子
alter table sale_detail touch;
參數(shù)說明:
table_name:必填。待修改表的修改時間的表名稱。
具體語句5:重命名表
alter table <table_name> rename to <new_table_name>;
--------------------------------------------------------
--例子
alter table sale_detail rename to sale_detail_rename;
參數(shù)說明:
table_name:必填。待修改名稱的表。
new_table_name:必填。修改后的表名稱。如果已存在與new_table_name同名的表,會返回報錯。
具體語句6:刪除表
drop table [if exists] <table_name>;
--------------------------------------------------------
--例子
drop table if exists sale_detail;
參數(shù)說明:
if exists:可選。如果不指定if exists且表不存在,則返回異常。如果指定if exists,無論表是否存在,均返回成功。
table_name:必填。待刪除的表名。
具體語句7:查看表或視圖信息
--查看表或視圖信息。
desc <table_name|view_name> [partition (<pt_spec>)];
--查看外部表、聚簇表或Transactional表信息。也可以查看內(nèi)部表的擴展信息。
desc extended <table_name>;
--------------------------------------------------------
--例子
desc test1;
參數(shù)說明:
table_name:必填。待查看表的名稱。
view_name:必填。待查看視圖的名稱。
pt_spec:可選。待查看分區(qū)表的指定分區(qū)。
extended:如果表為外部表、聚簇表或Transactional表,需要包含此參數(shù)。
具體語句8:查看分區(qū)信息
desc <table_name> partition (<pt_spec>);
--------------------------------------------------------
--例子
--查詢分區(qū)表sale_detail的分區(qū)信息。
desc sale_detail partition (xxxx_date='201310',region='beijing');
參數(shù)說明:
table_name:必填。待查看分區(qū)信息的分區(qū)表名稱。
pt_spec:必填。待查看的分區(qū)信息。
具體語句9:查看建表語句
show create table <table_name>;
--------------------------------------------------------
--例子
--查看表sale_detail的建表語句。
show create table sale_detail;
參數(shù)說明:
table_name:必填。待查看建表語句的表的名稱。
具體語句10:列出所有分區(qū)
show partitions <table_name>;
--------------------------------------------------------
--例子
--列出sale_detail中的所有分區(qū)。
show partitions sale_detail;
參數(shù)說明:
table_name:必填。待查看分區(qū)信息的分區(qū)表名稱。
具體語句11:清空列數(shù)據(jù)
ALTER TABLE <table_name>
[partition ( <pt_spec>[, <pt_spec>....] )]
CLEAR COLUMN column1[, column2, column3, ...]
[without touch];
參數(shù)說明:
table_name:將要執(zhí)行清空列數(shù)據(jù)的表名稱。
column1 , column2...:將要被清空數(shù)據(jù)的列名稱。
partition:指定分區(qū)。
pt_spec:分區(qū)描述。
without touch:表示不更新LastDataModifiedTime。
具體語句12:復制表
clone table <[<src_project_name>.]<src_table_name>> [partition(<pt_spec>), ...]
to <[<dest_project_name>.]<dest_table_name>> [if exists [overwrite | ignore]] ;
----------------------------------------------------------------------------
--例子
--復制表數(shù)據(jù)。
clone table xxxx_detail partition (xxxx_date='2013', region='china') to xxxx_detail_clone if exists overwrite;
參數(shù)說明:
src_project_name:可選。源表所屬MaxCompute項目名稱。
src_table_name:必填。源表名稱。
pt_spec:可選。源表的分區(qū)信息。
dest_project_name:可選。
dest_table_name:必填。目標表名稱。
具體語句1:插入或覆寫數(shù)據(jù)
--插入:直接向表或靜態(tài)分區(qū)中插入數(shù)據(jù),可以在insert語句中直接指定分區(qū)值,將數(shù)據(jù)插入指定的分區(qū)。如果您需要插入少量測試數(shù)據(jù),可以配合VALUES使用。
--覆寫:先清空表或靜態(tài)分區(qū)中的原有數(shù)據(jù),再向表或靜態(tài)分區(qū)中插入數(shù)據(jù)。
insert {into|overwrite} table <table_name> [partition (<pt_spec>)] [(<col_name> [,<col_name> ...)]]
<select_statement>
from <from_statement>
[zorder by <zcol_name> [, <zcol_name> ...]];
----------------------------------------------------------------------------
--例子
--向源表追加數(shù)據(jù)。其中:insert into table table_name可以簡寫為insert into table_name,但insert overwrite table table_name不可以省略table關鍵字。
insert into xxxx_detail partition (xxxx_date='2013', region='china') values ('s1','c1',100.1),('s2','c2',100.2),('s3','c3',100.3);
--執(zhí)行insert overwrite命令向表xxxx_detail_insert中覆寫數(shù)據(jù),調(diào)整select子句中列的順序。
insert overwrite table xxxx_detail_insert partition (xxxx_date='2013', region='china')
select xxxx_id, xxxx_name, xxxx_price from xxxx_detail;
參數(shù)說明:
table_name:必填。需要插入數(shù)據(jù)的目標表名稱。
pt_spec:可選。需要插入數(shù)據(jù)的分區(qū)信息。
col_name:可選。需要插入數(shù)據(jù)的目標表的列名稱。
select_statement:必填。select子句,從源表中查詢需要插入目標表的數(shù)據(jù)。
from_statement:必填。from子句,表示數(shù)據(jù)來源。
zorder by <zcol_name> [, <zcol_name> ...]:可選。向表或分區(qū)寫入數(shù)據(jù)時,支持根據(jù)指定的一列或多列,把排序列數(shù)據(jù)相近的行排列在一起,提升查詢時的過濾性能,在一定程度上降低存儲成本。
具體語句2:插入或覆寫動態(tài)分區(qū)數(shù)據(jù)
--在使用MaxCompute SQL處理數(shù)據(jù)時,分區(qū)列的值在select子句中提供,系統(tǒng)自動根據(jù)分區(qū)列的值將數(shù)據(jù)插入到相應分區(qū)。
insert {into|overwrite} table <table_name> partition (<ptcol_name>[, <ptcol_name> ...])
<select_statement> from <from_statement>;
----------------------------------------------------------------------------
--例子
--指定一級分區(qū),將數(shù)據(jù)插入目標表。
insert overwrite table sale_detail_dypart partition (sale_date='2013', region)
select shop_name,customer_id,total_price,region from sale_detail;
--將源表sale_detail中的數(shù)據(jù)插入到目標表sale_detail_dypart。
insert overwrite table sale_detail_dypart partition (sale_date, region)
select shop_name,customer_id,total_price,sale_date,region from sale_detail;
參數(shù)說明:
table_name:必填。需要插入數(shù)據(jù)的目標表名。
ptcol_name:必填。目標表分區(qū)列的名稱。
select_statement:必填。select子句,從源表中查詢需要插入目標表的數(shù)據(jù)。
from_statement:必填。from子句,表示數(shù)據(jù)來源。例如,源表名稱。
具體語句3:更新或刪除數(shù)據(jù)
--刪除操作:用于刪除Transactional或Delta Table表中滿足指定條件的單行或多行數(shù)據(jù)。
delete from <table_name> [where <where_condition>];
--清空列數(shù)據(jù):將不再使用的列數(shù)據(jù)從磁盤刪除并置NULL,從而達到降低存儲成本的目的。
ALTER TABLE <table_name>
[partition ( <pt_spec>[, <pt_spec>....] )]
CLEAR COLUMN column1[, column2, column3, ...]
[without touch];
--更新操作:用于將Transactional表或Delta Table表中行對應的單列或多列數(shù)據(jù)更新為新值。
--方式1
update <table_name> set <col1_name>=<value1> [, <col2_name>=<value2> ...] [WHERE <where_condition>];
--方式2
update <table_name> set (<col1_name> [, <col2_name> ...])=(<value1> [, <value2> ...])[WHERE <where_condition>];
--方式3
UPDATE <table_name>
SET <col1_name>=<value1> [ , <col2_name>=<value2> , ... ]
[ FROM <additional_tables> ]
[ WHERE <where_condition> ]
參數(shù)說明:
table_name:必填。
where_condition:可選。WHERE子句,用于篩選滿足條件的數(shù)據(jù)。
partition:指定分區(qū),若未指定,則表示操作所有分區(qū)。
pt_spec:分區(qū)描述。
without touch:表示不更新LastDataModifiedTime。
col1_name、col2_name:待修改行對應的列名稱。
value1、value2:至少更新一個列值。修改后的新值。
where_condition:可選。WHERE子句,用于篩選滿足條件的數(shù)據(jù)。
additional_tables:可選,from子句。
具體語句4:merge into
merge into <target_table> as <alias_name_t> using <source expression|table_name> as <alias_name_s>
--從on開始對源表和目標表的數(shù)據(jù)進行關聯(lián)判斷。
on <boolean expression1>
--when matched…then指定on的結(jié)果為True的行為。多個when matched…then之間的數(shù)據(jù)無交集。
when matched [and <boolean expression2>] then update set <set_clause_list>
when matched [and <boolean expression3>] then delete
--when not matched…then指定on的結(jié)果為False的行為。
when not matched [and <boolean expression4>] then insert values <value_list>
----------------------------------------------------------------------------
--例子
--執(zhí)行merge into操作,對符合on條件的數(shù)據(jù)用源表的數(shù)據(jù)對目標表進行更新操作,對不符合on條件并且源表中滿足event_type為I的數(shù)據(jù)插入目標表。命令示例如下:
merge into acid_address_book_base1 as t using tmp_table1 as s
on s.id=t.id and t.year='2020' and t.month='08' and t.day='20' and t.hour='16'
when matched then update set t.first_name=s.first_name, t.last_name=s.last_name, t.phone=s.phone
when not matched and (s._event_type_='I') then insert values(s.id, s.first_name, s.last_name,s.phone,'2020','08','20','16');
參數(shù)說明:
target_table:必填。目標表名稱,必須是實際存在的表。
alias_name_t:必填。目標表的別名。
source expression|table_name:必填。關聯(lián)的源表名稱、視圖或子查詢。
alias_name_s:必填。關聯(lián)的源表、視圖或子查詢的別名。
boolean expression1:必填。BOOLEAN類型判斷條件,判斷結(jié)果必須為True或False。
boolean expression2:可選。update、delete、insert操作相應的BOOLEAN類型判斷條件。
set_clause_list:當出現(xiàn)update操作時必填。
value_list:當出現(xiàn)insert操作時必填。
具體語句5:Values
--insert … values
insert into table <table_name>
[partition (<pt_spec>)][(<col1_name> ,<col2_name>,...)]
values (<col1_value>,<col2_value>,...),(<col1_value>,<col2_value>,...),...
--values table
values (<col1_value>,<col2_value>,...),(<col1_value>,<col2_value>,...),<table_name> (<col1_name> ,<col2_name>,...)...
參數(shù)說明:
table_name:必填。待插入數(shù)據(jù)的表名稱。
pt_spec:可選。需要插入數(shù)據(jù)的目標分區(qū)信息。
col_name:可選。需要插入數(shù)據(jù)的目標列名稱。
col_value:可選。目標表中列對應的列值。
具體語句6:Load
--將Hologres、OSS、Amazon Redshift、BigQuery外部存儲的CSV格式或其他開源格式數(shù)據(jù)導入MaxCompute的表或表的分區(qū)。
{load overwrite|into} table <table_name> [partition (<pt_spec>)]
from location <external_location>
stored by <StorageHandler>
[with serdeproperties (<Options>)];
----------------------------------------------------------------------------
--例子
load overwrite table xxxx_data_csv_load
from
location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/mc-test/data_location/'
stored by 'com.aliyun.odps.CsvStorageHandler'
with serdeproperties (
'odps.properties.rolearn'='acs:ram::xxxxx:role/aliyunodpsdefaultrole', --AliyunODPSDefaultRole的ARN信息,可通過RAM角色管理頁面獲取。
'odps.text.option.delimiter'=','
);
參數(shù)說明:
table_name:必填。需要插入數(shù)據(jù)的目標表名稱。
pt_spec:可選。需要插入數(shù)據(jù)的目標表分區(qū)信息。
external_location:必填。指定讀取外部存儲數(shù)據(jù)的OSS目錄。
StorageHandler:必填。指定內(nèi)置的StorageHandler名稱。
Options:可選。指定外部表相關參數(shù)。
具體語句7:Unload
--將MaxCompute的數(shù)據(jù)導出至OSS、Hologres外部存儲,OSS支持以CSV格式或其他開源格式存儲數(shù)據(jù)。
unload from {<select_statement>|<table_name> [partition (<pt_spec>)]}
into
location <external_location>
stored by <StorageHandler>
[with serdeproperties ('<property_name>'='<property_value>',...)];
----------------------------------------------------------------------------
--例子
--控制導出文件個數(shù):設置單個Worker讀取MaxCompute表數(shù)據(jù)的大小,單位為MB。由于MaxCompute表有壓縮,導出到OSS的數(shù)據(jù)一般會膨脹4倍左右。
set odps.stage.mapper.split.size=256;
--導出數(shù)據(jù)。
unload from sale_detail partition (sale_date='2013',region='china')
into
location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/mc-unload/data_location'
stored by 'com.aliyun.odps.TsvStorageHandler'
with serdeproperties ('odps.properties.rolearn'='acs:ram::139699392458****:role/AliyunODPSDefaultRole', 'odps.text.option.gzip.output.enabled'='true');
參數(shù)說明:
select_statement:select查詢子句,
table_name、pt_spec:使用表名稱或表名稱加分區(qū)名稱的方式指定需要導出的數(shù)據(jù)。
external_location:必填。
StorageHandler:必填。指定內(nèi)置的StorageHandler名稱。
<property_name>'='<property_value>':可選。property_name為屬性名稱,property_value為屬性值。
具體語句8:Explain
--分析查詢語句或表結(jié)構(gòu)來分析性能瓶頸
explain <dml query>;
----------------------------------------------------------------------------
--例子
explain
select a.customer_id as ashop, sum(a.total_price) as ap,count(b.total_price) as bp
from (select * from sale_detail_jt where sale_date='2013' and region='china') a
inner join (select * from sale_detail where sale_date='2013' and region='china') b
on a.customer_id=b.customer_id
group by a.customer_id
order by a.customer_id
limit 10;
參數(shù)說明:
dml query:必填。select語句。
具體語句9:公用表表達式
--臨時命名結(jié)果集,用于簡化SQL,可以更好地提高SQL語句的可讀性與執(zhí)行效率
with
<cte_name> as
(
<cte_query>
)
[,<cte_name2> as
(
<cte_query2>
)
,……]
----------------------------------------------------------------------------
--例子
with
a as (select * from src where key is not null),
b as (select * from src2 where value > 0),
c as (select * from src3 where value > 0),
d as (select a.key, b.value from a join b on a.key=b.key),
e as (select a.key,c.value from a left outer join c on a.key=c.key and c.key is not null)
insert overwrite table srcp partition (p='abc')
select * from d union all select * from e;
參數(shù)說明:
cte_name:必填。CTE的名稱,不能與當前with子句中的其他CTE的名稱相同。查詢中任何使用到cte_name標識符的地方,均指CTE。
cte_query:必填。一個select語句。select的結(jié)果集用于填充CTE。
1. SELECT語法
[with <cte>[, ...] ]
SELECT [all | distinct] <SELECT_expr>[, <except_expr>][, <replace_expr>] ...
from <table_reference>
[where <where_condition>]
[group by {<col_list>|rollup(<col_list>)}]
[having <having_condition>]
[window <window_clause>]
[order by <order_condition>]
[distribute by <distribute_condition> [sort by <sort_condition>]|[ cluster by <cluster_condition>] ]
[limit <number>]
下面將介紹SELECT命令格式及如何實現(xiàn)嵌套查詢、分組查詢、排序等操作。
2. SELECT語序
--語法順序
from <table_reference>
[where <where_condition>]
[group by <col_list>]
[having <having_condition>]
[window <window_name> AS (<window_definition>)]
[qualify <expression>]
select [all | distinct] <select_expr>, <select_expr>, ...
[order by <order_condition>]
[distribute by <distribute_condition> [sort by <sort_condition>] ]
[limit <number>]
場景1:from->where->group by->having->select->order by->limit
場景2:from->where->select->distribute by->sort by
3. WITH子句
with
A as (SELECT 1 as C),
B as (SELECT * from A)
SELECT * from B;
在同一WITH子句中的CTE必須具有唯一的名字。
在WITH子句中定義的CTE僅對在同一WITH子句中的其他CTE可以使用。
4. 列表達式
----------------------------------------------------------------------------
--例子
--讀取表xxxx_detail的列shop_name
SELECT xxxx_name from xxxx_detail;
--查詢表xxxx_detail中region列數(shù)據(jù),如果有重復值時僅顯示一條。
SELECT distinct region from xxxx_detail;
--選出xxxx_detail表中列名不為xxxx_name的所有列
SELECT `(xxxx_name)?+.+` from xxxx_detail;
--去重多列時,distinct的作用域是SELECT的列集合,不是單個列。
SELECT distinct region, xxxx_date from xxxx_detail;
用列名指定要讀取的列。
用星號(*)代表查詢所有的列。
可以使用正則表達式。
在選取的列名前可以使用distinct去掉重復字段,只返回去重后的值。
5. 排除列
--讀取xxxx_detail表的數(shù)據(jù),并排除region列的數(shù)據(jù)。
----------------------------------------------------------------------------
--例子
SELECT * except(region) from xxxx_detail;
當希望讀取表內(nèi)大多數(shù)列的數(shù)據(jù),同時要排除表中少數(shù)列的數(shù)據(jù)時。
表示讀取表數(shù)據(jù)時會排除指定列(col1、col2)的數(shù)據(jù)。
6. WHERE
--配合關系運算符,篩選滿足指定條件的數(shù)據(jù)。關系運算符包含:
>、<、=、>=、<=、<>
like、rlike
in、not in
between…and
----------------------------------------------------------------------------
--例子
SELECT *
from xxxx_detail
where xxxx_date >='2008' and xxxx_date <='2014';
--等價于如下語句。
SELECT *
from xxxx_detail
where xxxx_date between '2008' and '2014';
where子句為過濾條件。如果表是分區(qū)表,可以實現(xiàn)列裁剪。
7. GROUP BY
----------------------------------------------------------------------------
--例子
--直接使用輸入表列名region作為group by的列,即以region值分組
SELECT region from xxxx_detail group by region;
--以region值分組,返回每一組的銷售額總量。
SELECT sum(xxxx_price) from xxxx_detail group by region;
--以region值分組,返回每一組的region值(組內(nèi)唯一)及銷售額總量。
SELECT region, sum (xxxx_price) from xxxx_detail group by region;
group by操作優(yōu)先級高于SELECT操作,因此group by的取值是SELECT輸入表的列名或由輸入表的列構(gòu)成的表達式。需要注意的是:
group by取值為正則表達式時,必須使用列的完整表達式。
SELECT語句中沒有使用聚合函數(shù)的列必須出現(xiàn)在GROUP BY中。
8. HAVING
----------------------------------------------------------------------------
--例子
--為直觀展示數(shù)據(jù)呈現(xiàn)效果,向sale_detail表中追加數(shù)據(jù)。
insert into sale_detail partition (sale_date='2014', region='shanghai')
values ('null','c5',null),('s6','c6',100.4),('s7','c7',100.5);
--使用having子句配合聚合函數(shù)實現(xiàn)過濾。
SELECT region,sum(total_price) from sale_detail
group by region
having sum(total_price)<305;
通常HAVING子句與聚合函數(shù)一起使用,實現(xiàn)過濾。
9. ORDER BY
----------------------------------------------------------------------------
--例子
--查詢表xxxx_detail的信息,并按照xxxx_price升序排列前2條。
SELECT * from xxxx_detail order by xxxx_price limit 2;
--將表xxx_detail按照xxxx_price升序排序后,輸出從第3行開始的3行數(shù)據(jù)。
SELECT xxxx_id,xxxx_price from xxxx_detail order by xxxx_price limit 3 offset 2;
默認對數(shù)據(jù)進行升序排序,如果降序排序,需要使用desc關鍵字。
order by默認要求帶limit數(shù)據(jù)行數(shù)限制,沒有l(wèi)imit會返回報錯。
10. DISTRIBUTE BY哈希分片
----------------------------------------------------------------------------
--例子
--查詢表xxxx_detail中的列region值并按照region值進行哈希分片。
SELECT region from xxxx_detail distribute by region;
--等價于如下語句。
SELECT region as r from xxxx_detail distribute by region;
SELECT region as r from xxxx_detail distribute by r;
distribute by控制Map(讀數(shù)據(jù))的輸出在Reducer中是如何劃分的,如果不希望Reducer的內(nèi)容存在重疊,或需要對同一分組的數(shù)據(jù)一起處理,可以使用distribute by來保證同組數(shù)據(jù)分發(fā)到同一個Reducer中。
11. SORT BY局部排序
----------------------------------------------------------------------------
--例子
--查詢表xxxx_detail中的列region和xxxx_price的值并按照region值進行哈希分片,然后按照xxxx_price對哈希分片結(jié)果進行局部升序排序。
SELECT region,xxxx_price from xxxx_detail distribute by region sort by xxxx_price;
--查詢表xxxx_detail中的列region和xxxx_price的值并按照region值進行哈希分片,然后按照xxxx_price對哈希分片結(jié)果進行局部降序排序。
SELECT region,xxxx_price from xxxx_detail distribute by region sort by xxxx_price desc;
--如果sort by語句前沒有distribute by,sort by會對每個Reduce中的數(shù)據(jù)進行局部排序。
SELECT region,xxxx_price from xxxx_detail sort by xxxx_price desc;
sort by默認對數(shù)據(jù)進行升序排序,如果降序排序,需要使用desc關鍵字。
如果sort by語句前有distribute by,sort by會對distribute by的結(jié)果按照指定的列進行排序。
12. LIMIT限制輸出行數(shù)
SELECT * FROM xxxxx.xxxx_xxxx_xxxx
WHERE ds=20240520
LIMIT 100;
limit <number>中的number是常數(shù),用于限制輸出行數(shù),取值范圍為int32位取值范圍。
1. 基礎子查詢
--格式1
select <select_expr> from (<select_statement>) [<sq_alias_name>];
--格式2
select (<select_statement>) from <table_name>;
普通查詢操作的對象是目標表,但是查詢的對象也可以是另一個select語句,這種查詢?yōu)樽硬樵儭T趂rom子句中,子查詢可以被當作一張表,與其他表或子查詢進行join操作。
2. IN SUBQUERY
--in subquery與left semi join用法類似
--格式一
select<select_expr1>from<table_name1>where<select_expr2>
in(select<select_expr3>from<table_name2>);
--等效于leftsemijoin如下語句。
select<select_expr1>from<table_name1><alias_name1>leftsemijoin<table_name2><alias_name2>
on<alias_name1>.<select_expr2>=<alias_name2>.<select_expr3>;
--格式二
select<select_expr1>from<table_name1>where<select_expr2>
in(select<select_expr3>from<table_name2>where
<table_name1>.<col_name>=<table_name2>.<col_name>);
----------------------------------------------------------------------------
--例子
set odps.sql.allow.fullscan=true;
select * from xxxx_detail where xxxx_price in (select xxxx_price from shop);
set odps.sql.allow.fullscan=true;
select * from xxxx_detail where xxxx_price
in (select xxxx_price from shop where xxxx_id=shop.xxxx_id);
select_expr1:必填。格式為col1_name, col2_name, 正則表達式,...,表示待查詢的普通列、分區(qū)列或正則表達式。
table_name1、table_name2:必填。表的名稱。
select_expr2、select_expr3:必填。表示table_name1和table_name2互相映射的列名。
col_name:必填。表的列名。
3. NOT IN SUBQUERY
--如果查詢目標表的指定列名中有任意一行為NULL,則not in表達式值為NULL,導致where條件不成立,無數(shù)據(jù)返回
select <select_expr1> from <table_name1> where <select_expr2> not in (select <select_expr2> from <table_name2>);
--等效于left anti join如下語句。
select <select_expr1> from <table_name1> <alias_name1>
left anti join <table_name2> <alias_name2> on <alias_name1>.<select_expr1>=<alias_name2>.<select_expr2>;
----------------------------------------------------------------------------
--例子
--創(chuàng)建一張新表shop1并追加數(shù)據(jù)。
create table shop1 as select xxxx_name,xxxx_id,xxxx_price from xxxx_detail;
insert into shop1 values ('s8','c1',100.1);
select * from shop1 where xxxx_name not in (select xxxx_name from xxxx_detail);
set odps.sql.allow.fullscan=true;
select * from shop1 where xxxx_name not in (select xxxx_name from xxxx_detail where xxxx_id=shop1.xxxx_id);
select_expr1:必填。格式為col1_name, col2_name, 正則表達式,...,表示待查詢的普通列、分區(qū)列或正則表達式。
table_name1、table_name2:必填。表的名稱。
select_expr2、select_expr3:必填。表示table_name1和table_name2互相映射的列名。
col_name:必填。表的列名。
4. EXISTS SUBQUERY
--使用exists subquery時,當子查詢中有至少一行數(shù)據(jù)時,返回True,否則返回False。
select <select_expr> from <table_name1> where exists
(select <select_expr> from <table_name2>
where <table_name2_colname>=<table_name1>.<colname>
);
----------------------------------------------------------------------------
--例子
set odps.sql.allow.fullscan=true;
select * from xxxx_detail where exists
(select * from shop where customer_id=xxxx_detail.xxxx_id);
--等效于以下語句。
select * from xxxx_detail a left semi join shop b on a.xxxx_id=b.xxxx_id;
select_expr:必填。格式為col1_name, col2_name, 正則表達式,...,表示待查詢的普通列、分區(qū)列或正則表達式。
table_name1、table_name2:必填。表的名稱。
col_name:必填。表的列名。
5. NOT EXISTS SUBQUERY
--當子查詢中無數(shù)據(jù)時,返回True,否則返回False
select <select_expr> from <table_name1> where not exists
(select <select_expr> from <table_name2> where <table_name2_colname>=<table_name1>.<colname>);
----------------------------------------------------------------------------
--例子
set odps.sql.allow.fullscan=true;
select * from xxxx_detail where not exists (select * from shop where xxxx_name=xxxx_detail.xxxx_name);
--等效于以下語句。
select * from xxxx_detail a left anti join shop b on a.shop_name=b.xxxx_name;
select_expr:必填。格式為col1_name, col2_name, 正則表達式,...,表示待查詢的普通列、分區(qū)列或正則表達式。
table_name1、table_name2:必填。表的名稱。
col_name:必填。表的列名。
6. SCALAR SUBQUERY
--當子查詢的輸出結(jié)果為單行單列時,可以做為標量使用,即可以參與標量運算。
select <select_expr> from <table_name1> where
(<select count(*) from <table_name2> where <table_name2_colname>=<table_name1>.<colname>)
<標量運算符> <scalar_value>;
----------------------------------------------------------------------------
--例子
set odps.sql.allow.fullscan=true;
select * from shop where
(select count(*) from xxxx_detail where xxxx_detail.xxxx_name=shop.xxxx_name) >=1;
select_expr:必填。格式為col1_name, col2_name, 正則表達式。
table_name1、table_name2:必填。表的名稱。
col_name:必填。表的列名。
標量運算符:必填。例如大于(>)、小于(<)、等于(=)。
scalar_value:必填。標量值
1. 交集
--取交集不去重。
<select_statement1> intersect all <select_statement2>;
--取交集并去重。intersect效果等同于intersect distinct。
<select_statement1> intersect [distinct] <select_statement2>;
----------------------------------------------------------------------------
--例子
select * from values (1, 2), (1, 2), (3, 4), (5, 6) t(a, b)
intersect all
select * from values (1, 2), (1, 2), (3, 4), (5, 7) t(a, b);
--結(jié)果
+------------+------------+
| a | b |
+------------+------------+
| 1 | 2 |
| 3 | 4 |
+------------+------------+
select_statement1、select_statement2:必填。
distinct:可選。對兩個數(shù)據(jù)集取交集的結(jié)果去重。
2. 并集
--取并集不去重。
<select_statement1> union all <select_statement2>;
--取并集并去重。
<select_statement1> union [distinct] <select_statement2>;
----------------------------------------------------------------------------
--例子
select * from values (1, 2), (1, 2), (3, 4) t(a, b)
union all
select * from values (1, 2), (1, 4) t(a, b);
--結(jié)果
+------------+------------+
| a | b |
+------------+------------+
| 1 | 2 |
| 1 | 2 |
| 3 | 4 |
| 1 | 2 |
| 1 | 4 |
+------------+------------+
select_statement1、select_statement2:必填。select語句。
distinct:可選。對兩個數(shù)據(jù)集取并集的結(jié)果去重。
3. 補集
--取補集不去重。
<select_statement1> except all <select_statement2>;
<select_statement1> minus all <select_statement2>;
--取補集并去重。
<select_statement1> except [distinct] <select_statement2>;
<select_statement1> minus [distinct] <select_statement2>;
----------------------------------------------------------------------------
--例子
select * from values (1, 2), (1, 2), (3, 4), (3, 4), (5, 6), (7, 8) t(a, b)
except all
select * from values (3, 4), (5, 6), (5, 6), (9, 10) t(a, b);
--結(jié)果
+------------+------------+
| a | b |
+------------+------------+
| 1 | 2 |
| 1 | 2 |
| 3 | 4 |
| 7 | 8 |
+------------+------------+
select_statement1、select_statement2:必填。select語句。
distinct:可選。對取補集的結(jié)果去重。
這里先放一張示意圖:
--基本格式
SELECT column1, column2, ...
FROM table1
{left outer|right outer|full outer|inner|natural}
JOIN table2
ON condition;
參數(shù)說明:
column1, column2, ...:要選擇的字段名稱,可以為多個字段。如果不指定字段名稱,則會選擇所有字段。
table1:要連接的第一個表。
table2:要連接的第二個表。
condition:連接條件,用于指定連接方式。
左連接(left outer join) 可簡寫為left join | 返回左表中的所有記錄,即使右表中沒有與之匹配的記錄。 |
右連接(right outer join) 可簡寫為right join | 返回右表中的所有記錄,即使左表中沒有與之匹配的記錄。 |
全連接(full outer join) 可簡寫為full join | 返回左右表中的所有記錄。 |
內(nèi)連接(inner join) 關鍵字inner可以省略 | 左右表中至少存在一個匹配行時,inner join返回數(shù)據(jù)行。 |
自然連接(natural join) | 參與join的兩張表根據(jù)字段名稱自動決定連接字段。 支持outer natural join,支持使用using子句執(zhí)行join,輸出字段中公共字段只出現(xiàn)一次。 |
隱式連接 | 即不指定join關鍵字執(zhí)行連接。 |
多路連接 | 多路join連接。支持通過括號指定join的優(yōu)先級,括號內(nèi)的join優(yōu)先級較高。 |
| MaxCompute支持半連接操作,通過右表過濾左表的數(shù)據(jù),使右表的數(shù)據(jù)不出現(xiàn)在結(jié)果集中,可以提高查詢性能。 |
2. LEFT SEMI JOIN | 當join條件成立時,返回左表中的數(shù)據(jù)。如果左表中滿足指定條件的某行數(shù)據(jù)在右表中出現(xiàn)過,則此行保留在結(jié)果集中。 |
3. LEFT ANTI JOIN | 當join條件不成立時,返回左表中的數(shù)據(jù)。如果左表中滿足指定條件的某行數(shù)據(jù)沒有在右表中出現(xiàn)過,則此行保留在結(jié)果集中。 |
4. MAPJOIN HINT | 當對一個大表和一個或多個小表執(zhí)行join操作時,可以在select語句中顯式指定mapjoin Hint提示以提升查詢性能。 |
5. 在select語句中,使用Hint提示/*+ mapjoin(<table_name>) */才會執(zhí)行mapjoin | 引用小表或子查詢時,需要引用別名。 mapjoin支持小表為子查詢。 在mapjoin中,可以使用不等值連接或or連接多個條件。您可以通過不寫on語句而通過mapjoin on 1=1的形式,實現(xiàn)笛卡爾乘積的計算。 mapjoin中多個小表用英文逗號(,)分隔,例如/*+ mapjoin(a,b,c)*/。 |
--允許分區(qū)表的全表掃描
SET odps.sql.allow.fullscan=true;
-- 使用mapjoin查詢
select /*+ mapjoin(a) */
a.xxxx_name,
a.xxxx_price,
b.xxxx_price
from xxxx_detail_sj a join xxxx_detail b
on a.xxxx_price < b.xxxx_price or a.xxxx_price + b.xxxx_price < 500;
其原理圖:
--方法1:Hint表名(注意Hint的是表的alias)。
select /*+ skewjoin(a) */ * from T0 a join T1 b on a.c0=b.c0 and a.c1=b.c1;
--方法2:Hint表名和認為可能產(chǎn)生傾斜的列,例如表a的c0和c1列存在數(shù)據(jù)傾斜。
select /*+ skewjoin(a(c0, c1)) */ * from T0 a join T1 b on a.c0=b.c0 and a.c1=b.c1 and a.c2=b.c2;
--方法3:Hint表名和列,并提供發(fā)生傾斜的key值。如果是STRING類型,需要加上引號。例如(a.c0=1 and a.c1="2")和(a.c0=3 and a.c1="4")的值都存在數(shù)據(jù)傾斜。
select /*+ skewjoin(a(c0, c1)((1, "2"), (3, "4"))) */ * from T0 a join T1 b on a.c0=b.c0 and a.c1=b.c1 and a.c2=b.c2;
當兩張表Join存在熱點,導致出現(xiàn)長尾問題時:
可以通過取出熱點key,將數(shù)據(jù)分為熱點數(shù)據(jù)和非熱點數(shù)據(jù)兩部分處理,最后合并的方式,提高Join效率。
--格式
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value
--例子
SELECT Customer,SUM(OrderPrice) FROM Orders
GROUP BY Customer
HAVING SUM(OrderPrice)<2000
MaxCompute SQL的WHERE關鍵字無法與聚合函數(shù)一起使用。
此時可以使用HAVING子句來實現(xiàn)。
表同步
這里以MySQL同步ODPS為例子,其他表同步過程也類似。
首先介紹一下步驟:
Step1:進入dataworks,選擇:數(shù)據(jù)開發(fā)(DataStudio) ——> 數(shù)據(jù)集成 ——> Di數(shù)據(jù)同步 節(jié)點:
Step2:配置來源去向
Step3: 填好調(diào)度配置
調(diào)度參數(shù),注意參數(shù)值不同,展示的時間也不同
注意調(diào)度周期,天級,小時級或其他周期
設置好調(diào)度依賴,即依賴哪些上級文件的產(chǎn)出,若無可填根節(jié)點:
Step4:同步信息填寫完成后,在調(diào)度配置里配置好調(diào)度信息,保存——>發(fā)布——>補數(shù)據(jù) 即可:
接下來,是一些經(jīng)驗總結(jié):
1、“數(shù)據(jù)來源”的“數(shù)據(jù)過濾”,不填表示全量同步MySQL的數(shù)據(jù);也可以使用類似(gmt_create='${bizdate}')條件來過濾,每次增量同步MySQL的數(shù)據(jù) |
2、“數(shù)據(jù)去向”的“一鍵生成目標表”功能,建表DDL語句需要人工檢查下:
|
3、“數(shù)據(jù)去向”的“分區(qū)信息”,當建的是分區(qū)表時,會自動出現(xiàn)該處的分區(qū)信息配置;若建的是非分區(qū)表,則不必配置 |
4、調(diào)度配置中,可以按需選擇天、小時或其他時間粒度調(diào)度任務 |
5、非該odps項目空間的表不能在該odps項目空間做同步任務 |
6、odps個別字段內(nèi)容太長,超出mysql表的該字段存儲限制,也會導致寫入idb失敗,報臟數(shù)據(jù)(修改idb表字段類型,可將對應字段類型修改為 longtext) |
7、idb表字段設為非null,但odps對應字段存在 null值,會導致寫入idb失敗,報臟數(shù)據(jù)(修改idb表定義,將對應字段改默認為null) |
8、odps字段和idb字段不必非得一對一保持應,可以手動選擇相關字段 連線 ,odps和idb字段可各有未參與同步的字段(注意:idb字段的剩余字段必須是可以自動填充或默認為null類型的) |
目前對于需要周期性導入ODPS分區(qū)表數(shù)據(jù)到Hologres, Holo提供了兩種導入方式:
方式一:一鍵可視化導入并且周期性導入,詳情見datastudio一鍵導入
方式二:使用sql導入,詳情見hologres sql
2. 配置信息,填寫同步信息。
3. 參數(shù)說明
參數(shù) | 配置項 | 說明 | 備注 |
MaxCompute源表選擇 | 目標連接 | Hologres的實例名 | 無 |
目標庫 | Hologres的DB名 | 無 | |
外部表來源 |
|
| |
外部表表名字 | 已有的外部表表名 | 外部表用于映射MaxCompute數(shù)據(jù),需要與同步數(shù)據(jù)的MaxCompute表對應 | |
目標表設置 | 目標Schema | 當前DB下的schema名 | 默認為public,也可以選擇新建schema并使用 |
目標表名 | 要導入數(shù)據(jù)的表名 | 需要同步表數(shù)據(jù)的內(nèi)表名稱,如已有表,執(zhí)行后原表和數(shù)據(jù)將被刪除重建 | |
目標表描述 | 為目標表添加comment | 無 | |
同步設置 | 同步字段 | 選擇需要同步的MaxCompute表字段 | 可以選擇全部字段,也可以選擇部分字段 |
分區(qū)配置 | 選擇需要同步的分區(qū)字段 | 當前Hologres僅支持一級分區(qū) | |
索引配置 | 為目標表構(gòu)建索引 | 索引的創(chuàng)建可以參見文檔設置表屬性 | |
SQL Script | SQL Script | 自動解析出當前運行的SQL,方便參照 | 無 |
若是您需要周期性導數(shù)據(jù),需要單機右側(cè)調(diào)度配置進行任務配置,并且保存作業(yè),然后點擊右上角發(fā)布,將作業(yè)發(fā)布至生產(chǎn)環(huán)境進行周期性調(diào)度。
4. 總結(jié)
方式一優(yōu)點:可視化操作,簡單快捷,方便小白用戶使用,能滿足一般場景的使用。
方式一缺點:不支持修改SQL邏輯,若是需要修改,需將SQL Copy再新建一個Hologres SQL節(jié)點,根據(jù)業(yè)務邏輯修改SQL即可。
先介紹一下操作步驟,基本和方式一相同。
2. 輸入業(yè)務流程名稱
3. 新建Hologres SQL
4. Hologres開發(fā):打開新建的Hologres SQL選擇對應Hologres實例,既可使用標準的Postgresql語言開發(fā)。
步驟1:準備MaxCompute表數(shù)據(jù)
--MaxCompute分區(qū)表DDL
CREATE TABLE IF NOT EXISTS public_data.dwd_product_movie_basic_info(
movie_name STRING COMMENT '電影名稱',
dirctor STRING COMMENT '導演',
scriptwriter STRING COMMENT '編劇',
area STRING COMMENT '制片地區(qū)/國家',
actors STRING COMMENT '主演',
`type` STRING COMMENT '類型',
movie_length STRING COMMENT '電影長度',
movie_date STRING COMMENT '上映日期',
movie_language STRING COMMENT '語言',
imdb_url STRING COMMENT 'imdb號'
)
PARTITIONED BY (ds STRING) STORED AS ALIORC;
--查看分區(qū)表的某個分區(qū)數(shù)據(jù)
SELECT * FROM public_data.xxxx_movie_basic_info WHERE ds='20170112';
步驟2:Hologres新建外部表
移步HoloStudio,在SQL Console中新建一張外部表,用于映射MaxCompute源頭表數(shù)據(jù)。外表的字段順序和字段類型需要和MaxCompute一一對應。示例使用import foreign schema語法新建外部表SQL如下:
import foreign schema public_data limit to (dwd_product_movie_basic_info)
from server odps_server into public options(if_table_exist 'update');
步驟3:Hologres新建真實存儲表
在Hologres中新建一張真實的存儲表,用于接收并存儲數(shù)據(jù)。因為本次示例是將MaxCompute分區(qū)表導入Hologres分區(qū)表,因此需要在Hologres中創(chuàng)建一張分區(qū)表。
BEGIN;
CREATE TABLE "public"."holo_dwd_product_movie_basic_info" (
"movie_name" text,
"dirctor" text,
"scriptwriter" text,
"area" text,
"actors" text,
"type" text,
"movie_length" text,
"movie_date" text,
"movie_language" text,
"imdb_url" text,
"ds" text
)
PARTITION BY LIST (ds);
CALL SET_TABLE_PROPERTY('"public"."holo_dwd_product_movie_basic_info"', 'orientation', 'column');
CALL SET_TABLE_PROPERTY('"public"."holo_dwd_product_movie_basic_info"', 'bitmap_columns', '"movie_name","dirctor","scriptwriter","area","actors","type","movie_length","movie_date","movie_language","imdb_url","ds"');
CALL SET_TABLE_PROPERTY('"public"."holo_dwd_product_movie_basic_info"', 'dictionary_encoding_columns', '"movie_name:auto","dirctor:auto","scriptwriter:auto","area:auto","actors:auto","type:auto","movie_length:auto","movie_date:auto","movie_language:auto","imdb_url:auto","ds:auto"');
CALL SET_TABLE_PROPERTY('"public"."holo_dwd_product_movie_basic_info"', 'time_to_live_in_seconds', '3153600000');
comment on column "public"."holo_dwd_product_movie_basic_info"."movie_name" is '電影名稱';
comment on column "public"."holo_dwd_product_movie_basic_info"."dirctor" is '導演';
comment on column "public"."holo_dwd_product_movie_basic_info"."scriptwriter" is '編劇';
comment on column "public"."holo_dwd_product_movie_basic_info"."area" is '制片地區(qū)/國家';
comment on column "public"."holo_dwd_product_movie_basic_info"."actors" is '主演';
comment on column "public"."holo_dwd_product_movie_basic_info"."type" is '類型';
comment on column "public"."holo_dwd_product_movie_basic_info"."movie_length" is '電影長度';
comment on column "public"."holo_dwd_product_movie_basic_info"."movie_date" is '上映日期';
comment on column "public"."holo_dwd_product_movie_basic_info"."movie_language" is '語言';
comment on column "public"."holo_dwd_product_movie_basic_info"."imdb_url" is 'imdb號';
COMMIT;
步驟4:新建分區(qū)子表數(shù)據(jù)開發(fā)
在hologres sql中另開一個作業(yè),用于分區(qū)表跑調(diào)度。
--創(chuàng)建臨時分區(qū)子表
BEGIN;
CREATE TABLE IF NOT EXISTS "public".tmp_holo_dwd_product_movie_basic_info_${bizdate} (
"movie_name" text,
"dirctor" text,
"scriptwriter" text,
"area" text,
"actors" text,
"type" text,
"movie_length" text,
"movie_date" text,
"movie_language" text,
"imdb_url" text,
"ds" text
);
COMMIT;
--更新外表數(shù)據(jù)
import foreign schema public_data limit to (dwd_product_movie_basic_info) from server odps_server into public options(if_table_exist 'update');
--等待30s再導入Hologres,以防Hologres meta信息更新緩存慢導致的數(shù)據(jù)不一致而同步不成功
select pg_sleep(30);
--將Maxcompute數(shù)據(jù)導入臨時分區(qū)子表
INSERT INTO "public".tmp_holo_dwd_product_movie_basic_info_${bizdate}
SELECT
"movie_name",
"dirctor",
"scriptwriter",
"area",
"actors",
"type",
"movie_length",
"movie_date",
"movie_language",
"imdb_url",
"ds"
FROM "public".dwd_product_movie_basic_info
WHERE ds='${bizdate}';
--導入的場景邏輯比較多,下面有兩個場景供參考,可以根據(jù)業(yè)務邏輯二選一即可
--場景1:導入新的分區(qū)數(shù)據(jù)可以參考以下邏輯,
BEGIN;
ALTER TABLE "public".tmp_holo_dwd_product_movie_basic_info_${bizdate} RENAME TO holo_dwd_product_movie_basic_info_${bizdate};
--將臨時分區(qū)子表綁定在分區(qū)父表上
ALTER TABLE "public".holo_dwd_product_movie_basic_info ATTACH PARTITION "public".holo_dwd_product_movie_basic_info_${bizdate} FOR VALUES in ('${bizdate}');
COMMIT;
--場景2:重新對歷史分區(qū)數(shù)據(jù)刷新可以參考該邏輯
BEGIN;
ALTER TABLE IF EXISTS "public".holo_dwd_product_movie_basic_info DETACH PARTITION "public".holo_dwd_product_movie_basic_info_${bizdate};
DROP TABLE IF EXISTS "public".holo_dwd_product_movie_basic_info_${bizdate};
ALTER TABLE "public".tmp_holo_dwd_product_movie_basic_info_${bizdate} RENAME TO holo_dwd_product_movie_basic_info_${bizdate};
--將分區(qū)子表綁定在分區(qū)父表上
ALTER TABLE "public".holo_dwd_product_movie_basic_info ATTACH PARTITION "public".holo_dwd_product_movie_basic_info_${bizdate} FOR VALUES in ('${bizdate}');
COMMIT;
步驟5:調(diào)度配置
1)基礎屬性配置
將基礎屬性--參數(shù)賦值為時間節(jié)點,如示例所示:
2)時間屬性設置
主要設置時間的重跑屬性,其余參數(shù)可以根據(jù)業(yè)務情況自行設置。
3)調(diào)度依賴設置
調(diào)度依賴為root節(jié)點即可(也可以根據(jù)業(yè)務邏輯選擇已有的父節(jié)點)請先單擊自動解析為是,然后單擊使用工作空間根節(jié)點,會自動解析出root節(jié)點,然后將自動解析設置為否。
步驟6:發(fā)布調(diào)度
調(diào)度參數(shù)配置完成之后,單擊保存--提交,提交成功后單擊運維前往運維中心。
步驟7:運維中心發(fā)布
在跳轉(zhuǎn)出來的運維中心,選擇已提交成功成功的節(jié)點,右鍵單擊節(jié)點,選擇補數(shù)據(jù)--當前節(jié)點。并根據(jù)業(yè)務情況設置節(jié)點配置。
補完數(shù)據(jù)之后,在補數(shù)據(jù)實例可以看到正在運行的任務,以及任務運行狀態(tài)。
步驟8:Hologres查看數(shù)據(jù)
任務執(zhí)行成功之后,將會在Hologres中自動創(chuàng)建對應分區(qū)數(shù)據(jù)的分區(qū)子表,可以返回datastudio,新開一個hologres sql節(jié)點,執(zhí)行語句查詢數(shù)據(jù)是否寫入成功。
--查看分區(qū)子表數(shù)據(jù)
select * from holo_dwd_product_movie_basic_info_20170112;
--查看分區(qū)父表總數(shù)據(jù)
select count (*) from holo_dwd_product_movie_basic_info;
總結(jié):
方式二優(yōu)點:可按業(yè)務需求進行定制,對sql進行修改,滿足復雜特定場景的需求,包括歷史數(shù)據(jù)格式轉(zhuǎn)換、數(shù)據(jù)清理等;通過SQL導入性能更優(yōu)。
方式二缺點:有一定學習成本,初學者不太適合,可先通過方式一了解其數(shù)據(jù)同步的流程和原理,再切換到方式二。
-- 1.創(chuàng)建外表
CREATE FOREIGN TABLE IF NOT EXISTS ${odps_table_name} (
"user_id" bigint,
"user_name" text,
"ds" text
)
SERVER odps_server
OPTIONS (project_name 'onetag', table_name '${odps_table_name}');
COMMIT;
-- 2.刷新外表的Schema
IMPORT FOREIGN SCHEMA ${odps_project} LIMIT to
(
${odps_table_name}
)
FROM SERVER odps_server INTO public
OPTIONS(if_table_exist 'update',if_unsupported_type 'error');
-- 3.清理潛在的臨時表
BEGIN ;
DROP TABLE IF EXISTS ${holo_table_name}_tmp_${bizhour};
COMMIT ;
-- 4.創(chuàng)建臨時表
BEGIN ;
CREATE TABLE IF NOT EXISTS "public".${holo_table_name}_tmp_${bizhour} (
"user_id" bigint,
"user_name" text,
"ds" text,
PRIMARY KEY (user_id,ds)
);
COMMIT;
-- 5.通過查詢外表,向臨時表插入數(shù)據(jù)
INSERT INTO ${holo_table_name}_tmp_${bizhour}
SELECT *
FROM public.${odps_table_name}
WHERE ds='${bizhour}';
-- 6.替換子表
BEGIN ;
-- 6.1刪除已經(jīng)存在的子表
DROP TABLE IF EXISTS ${holo_table_name}_${bizhour};
-- 6.2將臨時表改名
ALTER TABLE ${holo_table_name}_tmp_${bizhour} RENAME TO ${holo_table_name}_${bizhour};
-- 6.3將臨時表綁定至指定分區(qū)表
ALTER TABLE ${holo_table_name} ATTACH PARTITION ${holo_table_name}_${bizhour}
FOR VALUES IN ('${bizhour}');
COMMIT ;
-- 7. 大量數(shù)據(jù)導入后執(zhí)行ANALYZE分區(qū)表父表操作
ANALYZE ${holo_table_name};
注意點:
注意事項
這里強調(diào)一下調(diào)度參數(shù):
調(diào)度參數(shù)通常會被用于指代某些動態(tài)時間的場景,此場景下,可基于業(yè)務日期和定時時間進行調(diào)度參數(shù)的取值設置。配置調(diào)度參數(shù)前,您可先了解這兩個時間概念,便于后續(xù)設置調(diào)度參數(shù)取值。
取值方式 | 參數(shù)格式 | 參數(shù)示例 | 相關參考 |
基于業(yè)務日期獲取時間數(shù)據(jù) | 通常,使用大括號${...},結(jié)合yyyy、yy、mm及dd自定義組合生成時間參數(shù),獲取業(yè)務日期前后多少年、月、天。 | 可通過${yyyymmdd}、${yyyy-mm-dd}等${...}自定義時間格式獲取,例如:
| 更多賦值示例,請參見自定義參數(shù)${...} |
基于定時時間獲取時間數(shù)據(jù) | 通常,使用中括號$[...],結(jié)合yyyy、yy、mm、dd、hh24、mi及ss自定義組合生成時間參數(shù),獲取定時時間前后多少年、月、天、小時、分鐘、秒。 | 可通過$[yyyymmddhh24miss]等$[...]自定義時間格式獲取。例如,取前一天的前一小時,參數(shù)表達式為$[yyyymmdd-1-1/24]。 |
|
內(nèi)置參數(shù):
內(nèi)置參數(shù) | 定義 |
$bizdate | 業(yè)務日期,格式為yyyymmdd,與自定義參數(shù)${yyyymmdd}取值一致。 該參數(shù)的應用較為廣泛,日常調(diào)度中默認任務預期運行時間的前一天為業(yè)務日期。 |
$cyctime | 任務的定時時間,格式為yyyymmddhh24miss,與自定義參數(shù)$[yyyymmddhh24miss]取值一致。 |
$gmtdate | 當前日期,格式為yyyymmdd。 該參數(shù)默認取當天日期,執(zhí)行補數(shù)據(jù)操作時輸入的日期為業(yè)務日期+1。 |
$bizmonth | 業(yè)務月份,格式為yyyymm。
|
$jobid | 任務所屬的業(yè)務流程ID。 |
$nodeid | 節(jié)點ID。 |
$taskid | 節(jié)點產(chǎn)生的實例ID。 |
調(diào)度配置的各板塊:
配置基礎屬性 | 名稱,節(jié)點ID,節(jié)點類型,責任人,描述 |
配置調(diào)度參數(shù) | 調(diào)度參數(shù)支持的格式 配置并使用調(diào)度參數(shù) |
配置時間屬性 | 時間屬性配置說明 實例生成方式:發(fā)布后即時生成實例 調(diào)度周期:分鐘/小時/天/月調(diào)度 |
配置資源屬性 | 默認配置為公共調(diào)度資源組。 |
配置調(diào)度依賴 | 調(diào)度依賴配置 配置同周期調(diào)度依賴 配置依賴上一周期(跨周期依賴) 復雜依賴場景調(diào)度配置原則 |
配置節(jié)點上下文 | 在節(jié)點上下文配置本節(jié)點輸入?yún)?shù)和本節(jié)點輸出參數(shù) 輸出參數(shù)的取值分為常量和變量兩種類型 配置輸入?yún)?shù),在調(diào)度依賴中添加依賴的上游節(jié)點 |
更多內(nèi)容請期待下一篇:進階篇。
證網(wǎng)訊(記者 董添)12月27日,記者從天下秀獲悉,公司旗下星礦科技總經(jīng)理張磊當選中關村云通計算機專業(yè)服務器系統(tǒng)技術創(chuàng)新聯(lián)盟(簡稱“創(chuàng)新聯(lián)盟”)副秘書長。
據(jù)了解,創(chuàng)新聯(lián)盟成立于2016年,是非盈利公共機構(gòu),其參與運營管理的文創(chuàng)品牌聯(lián)盟鏈由天下秀等多家上市公司及北京市國資委下屬企業(yè)共同成立。作為一條具有公共屬性的可治理開放型聯(lián)盟鏈,文創(chuàng)品牌聯(lián)盟鏈專注于為全國文化創(chuàng)意領域提供底層區(qū)塊鏈基礎設施和應用場景,致力于用技術驅(qū)動數(shù)字經(jīng)濟的新型基礎設施。星礦科技作為國內(nèi)公共區(qū)塊鏈最早的倡導者和數(shù)字經(jīng)濟領域平臺型企業(yè),為文創(chuàng)品牌聯(lián)盟鏈提供架構(gòu)設計和技術維護。
據(jù)創(chuàng)新聯(lián)盟相關負責人介紹,未來,文創(chuàng)品牌聯(lián)盟鏈將持續(xù)開發(fā)數(shù)字生活類應用、數(shù)字文旅類應用、數(shù)據(jù)資產(chǎn)服務應用、地標產(chǎn)品類應用、數(shù)字產(chǎn)業(yè)園區(qū)應用等內(nèi)容。