如何利用數倉創建時序表

摘要:怎麼快速上手,創建適合自己業務的時序表,怎樣使用才能真正發揮時序表的優勢。

本文分享自華爲雲社區《GaussDB(DWS)帶你走近IoT時代-時序表建表最佳實踐》,作者:AndyCao。

創建第一張時序表

我們首先來介紹一下如何創建一張時序表

語法格式

CREATE TABLE [ IF NOT EXISTS ] table_name
({ column_name data_type [ kv_type ] 
    | LIKE source_table [like_option [...] ] }
}
    [, ... ])
[ WITH ( {storage_parameter = value}  [, ... ] ) ]

[ TABLESPACE tablespace_name ]
[ DISTRIBUTE BY  HASH ( column_name [,...])]
[ TO { GROUP groupname | NODE ( nodename [, ... ] ) } ]
[ table_partitioning_clauses ]
[ PARTITION BY { 
        {RANGE (partition_key) ( partition_less_than_item [, ... ] )} 
 } [ { ENABLE | DISABLE } ROW MOVEMENT ] ]; 

其中like選項like_option爲:{ INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS | INDEXES | STORAGE | COMMENTS | PARTITION | RELOPTIONS | DISTRIBUTION | ALL }

時序表的建表語法,在很大程度上繼承了行存和列存的語法,降低了用戶的學習成本,能夠更容易理解和使用。我們上篇博客中介紹到,將時序表的列分爲三種kv_type類型(tag、field、time),那麼如何將對應的列指定爲合適的類型,幫助我們更好的提高導入、查詢等場景的性能,讓業務場景運行的更加高效呢?

我們繼續以發電機組的場景作爲示例,創建一張存儲發電機組採樣數據的時序表:

CREATE TABLE IF NOT EXISTS GENERATOR(
dynamo text TSTag,
manufacturer text TSTag,
model text TSTag,
location text TSTag,
ID bigint TSTag,
voltage numeric TSField,
power bigint TSTag,
frequency numeric TSField,
angle numeric TSField,
time timestamptz TSTime) with (orientation=TIMESERIES, period='7 days', ttl='1 month') distribute by hash(model);

我們可以看到,上述建表語句中:

  • 對於不隨時間的變化而變化,描述發電機的屬性信息的列(發電機信息、生產廠商、型號、位置、ID)被設置爲tag列,在建表時需要將對應的列後面指定爲TSTag;
  • 對於採樣數據的維度(電壓、功率、頻率、電流相角)這些對應的採樣數值隨時間的變化而變,我們將這些維度設置爲field列,建表語句數據類型後面指定爲TSField;
  • 最後一列我們指定爲時間列time,存儲field列數據對應的時間信息,建表時將指定爲TSTime。

在寫建表語句時,對於tag列的順序,我們可以適當優化一下,將唯一性(distinct值)較高的列儘量寫在前面,這樣對於時序場景的性能有一些提升。如果用戶沒有手動優化,GaussDB(DWS) IoT數倉也可以自適應的幫助用戶提高時序場景的性能,這後面我們會專門文章介紹這一黑科技

另外,創建時序表時一定要指定表級參數orientation屬性設置爲timeseries。時序表不需要手動指定DISTRIBUTE BY和PARTITION BY, 默認按照所有tag列分佈,且分區健默認爲tstim指定的時間列。

對於create table like語法,該語法需要自動從源表中繼承列名和對應的kv_type類型。因此如果源表是非時序表,新表是時序表,對應的列的kv_type類型無法確定,則無法創建成功。

時序表列類型

上面對時序表的三種kv_type屬性進行了簡單的說明:(維度屬性(TSTag),指標屬性(TSField),時間屬性(TSTime),那麼每個列他們支持的類型(類似建表語句中的text、int、numeric等)分別都是什麼呢?是否可以不設置kv_type類型?

首先時序表必須指定一個時間屬性(TSTime),且只能指定一個,且TSTime類型的列不能被刪除。至少存在一個TSTag和TSField列,否則建表報錯。

TSTag列支持類型:text, char, bool, int, big int。

TSTime列支持類型:timestamp with time zone, timestamp without time zone。在兼容Oracle語法的數據庫中,也支持date類型。涉及到時區相關操作時,請選擇帶時區的時間類型。

TSField列支持的數據類型同列存表保持一致

自動設置分區邊界

時序表具備數據生命週期管理的能力。每天數以億計的數據不間斷湧入,對於很久之前的數據,其價值較低不經常訪問,可以定期將無用的老數據刪除。並且由於最新的數據不斷進來,需要定期給表增加新的分區,避免新數據無法存儲。因此時序表需要具備定時增加分區和定時刪除分區的能力。

時序表以TSTIME列爲分區鍵,創建具有自動分區管理功能的分區表,幫助我們大大減少運維操作的工作。在上面的建表語句中,在表級參數項中可以看到,時序表指定了自動分區管理兩個參數period和ttl。

  • period:設置自動創建分區的間隔時間,默認值爲1 day, 取值範圍:1 hour ~ 100 years。默認會爲時序表創建自增分區任務。自增分區任務動態爲我們創建分區,保證當前時刻有足夠充裕的分區用於導入數據。
  • ttl:設置自動淘汰分區的時間,取值範圍:1 hour ~ 100 years。默認不創建淘汰分區任務,需要用戶自己在建表手動指定,或者建表後通過ALTER TABLE語法設置。淘汰分區的策略是通過計算 nowtime - 分區boundary > ttl,滿足該條件的分區將被drop掉。幫助用戶定時清理過期的舊數據。

上面舉得例子中,時序表建表語句沒有指定分區,那麼分區的起始時間是怎麼樣的。爲了方便用戶的使用,我們的分區邊界的設置分爲了一下幾種情況

  • period設置爲“小時” , 分區起始邊界值爲下個小時整點,分區的間隔爲period的值
  • period設置爲“天” , 分區起始邊界值爲第二天零點,分區的間隔爲period的值
  • period設置爲“月” , 分區起始邊界值爲下個月零點,分區的間隔爲period的值
  • period設置爲“年” , 分區起始邊界值爲明年零點,分區的間隔爲period的值
tsdb=# CREATE TABLE IF NOT EXISTS GENERATOR(
tsdb(# dynamo text TSTag,
tsdb(# manufacturer text TSTag,
tsdb(# model text TSTag,
tsdb(# location text TSTag,
tsdb(# ID bigint TSTag,
tsdb(# voltage numeric TSField,
tsdb(# power bigint TSTag,
tsdb(# frequency numeric TSField,
tsdb(# angle numeric TSField,
tsdb(# time timestamptz TSTime) with (orientation=TIMESERIES, period='1 hour', ttl='1 month') distribute by hash(model);
CREATE TABLE

tsdb=# select now();
              now
-------------------------------
 2022-05-25 15:28:38.520757+08
(1 row)
tsdb=# select relname, boundaries from pg_partition where parentid=(select oid from pg_class where relname='generator') order by boundaries ;
    relname     |         boundaries
----------------+----------------------------
 default_part_1 | {"2022-05-25 16:00:00+08"}
 default_part_2 | {"2022-05-25 17:00:00+08"}
 p1653505200    | {"2022-05-26 03:00:00+08"}
 p1653541200    | {"2022-05-26 13:00:00+08"}
 p1653577200    | {"2022-05-26 23:00:00+08"}
 ......

這樣的使用方式,能夠使得用戶能夠便捷快速的創建時序表。當然我們也支持在建表時用戶手動指定分區邊界的起始值。關於自動分區管理功能更詳細的描述,可以參考《GaussDB(DWS) 分區自動管理介紹》

tsdb=# select now();
              now
-------------------------------
 2022-05-31 20:36:09.700096+08
(1 row)

tsdb=# CREATE TABLE IF NOT EXISTS GENERATOR(
tsdb(# dynamo text TSTag,
tsdb(# manufacturer text TSTag,
tsdb(# model text TSTag,
tsdb(# location text TSTag,
tsdb(# ID bigint TSTag,
tsdb(# voltage numeric TSField,
tsdb(# power bigint TSTag,
tsdb(# frequency numeric TSField,
tsdb(# angle numeric TSField,
tsdb(# time timestamptz TSTime) with (orientation=TIMESERIES, period='1 day') distribute by hash(model)
tsdb-# partition by range(time)
tsdb-# (
tsdb(# PARTITION P1 VALUES LESS THAN('2022-05-30 16:32:45'),
tsdb(# PARTITION P2 VALUES LESS THAN('2022-05-31 16:56:12')
tsdb(# );
WARNING:  partition boundary is less than current time.
CREATE TABLE

tsdb=# select relname, boundaries from pg_partition where parentid=(select oid from pg_class where relname='generator') order by boundaries ;
   relname   |         boundaries
-------------+----------------------------
 p1          | {"2022-05-30 16:32:45+08"}
 p2          | {"2022-05-31 16:56:12+08"}
 p1654073772 | {"2022-06-01 16:56:12+08"}
 p1654160172 | {"2022-06-02 16:56:12+08"}
 ......

至此,我們已經建成了自己的第一張時序表,接下來我們會針對時序表的DDL各種操作進行詳細的實踐,幫助大家學好、用好時序數據庫,更好的爲用戶的業務服務。

 

點擊關注,第一時間瞭解華爲雲新鮮技術~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章