建筑設(shè)計(jì)作品展示網(wǎng)站吉林seo管理平臺(tái)
1. 簡(jiǎn)介
從 TDengine 3.3.0.0 版本之后,新增了復(fù)合主鍵的功能。
TDengine 原來的時(shí)間列是不允許有重復(fù)時(shí)間戳的,有了復(fù)合主鍵功能后,時(shí)間列即允許有重復(fù),重復(fù)后的時(shí)間戳按緊跟其后第二列主鍵列的值來確定唯一性。
此功能的常用場(chǎng)景如高速收費(fèi)口,同一時(shí)間內(nèi)可能會(huì)多輛車通過,股票交易記錄,同一時(shí)間內(nèi)筆成交等多種實(shí)際應(yīng)用場(chǎng)景。
2. 功能說明
2.1 建表
用戶可以在建表時(shí)用 PRIMARY KEY
關(guān)鍵字,額外指定除主鍵時(shí)間戳列以外的另一列作為主鍵列,該列與時(shí)間戳列共同組成一行數(shù)據(jù)的鍵值,其類型必須為整型(int32, int64, uint32, uint64) 或 字符串類型(varchar)。超級(jí)表與普通表均支持復(fù)合主鍵。復(fù)合主鍵列不支持修改、增加和刪除操作。PRIMARY KEY 列只能設(shè)置為第二列。
具體 SQL 語句如下:
CREATE TABLE t ( ts TIMESTAMP, obj_id VARCHAR(64) PRIMARY KEY, data1 FLOAT, data2 int );
2.2 寫入
只有當(dāng)時(shí)間戳相同且 PRIAMRY KEY 列值都相同時(shí),兩行數(shù)據(jù)才會(huì)被認(rèn)為是重復(fù)數(shù)據(jù),否則被認(rèn)為是兩行不同數(shù)據(jù)。如果時(shí)間戳相同但 Primary key 較小數(shù)據(jù)后寫入,則視為亂序數(shù)據(jù)處理。
schemaless 寫入不支持復(fù)合主鍵的情況,因?yàn)?schemaless 本身就是沒有 schema,沒法確定復(fù)合主鍵,目前的三種 schemaless 協(xié)議 (influxdb line/opentsdb telnet/opentsdb json) 也沒有復(fù)合主鍵這個(gè)概念。
2.3 刪除
刪除操作與現(xiàn)有刪除操作一樣,只支持按時(shí)間段刪除,不支持按主鍵范圍刪除。
2.4 查詢
2.4.1 數(shù)據(jù)讀取
查詢復(fù)合主鍵數(shù)據(jù)時(shí),時(shí)間戳相同且 PRIMARY KEY 列值相同時(shí),被認(rèn)為是一行數(shù)據(jù)。對(duì)于復(fù)合主鍵(時(shí)間戳+PRIMARY KEY 列)相同但被多次寫入的重復(fù)數(shù)據(jù)則在合并更新后返回。只有復(fù)合主鍵不同的行被認(rèn)為不同的行數(shù)據(jù),被查詢分別返回。每個(gè)表的讀取結(jié)果是按(時(shí)間戳主鍵,Primary Key)有序。其他查詢行為也將相應(yīng)地變動(dòng)。具體變化內(nèi)容見后續(xù)章節(jié)。
查詢行為的適配源自于TSDB reader 返回給上層的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu) SSDataBlock中包含了時(shí)間戳相同,但primary key 不同的記錄。
2.4.2 標(biāo)量查詢
此原來行為相同,無改變
2.4.3 聚合查詢
- 非時(shí)間窗口類:用戶可見層面無變化。
- 時(shí)間窗口聚合類:TDengine 系統(tǒng)中針對(duì)時(shí)間窗口采用閉區(qū)間進(jìn)行描述,并且相同時(shí)間戳不同primary key的記錄歸屬于同一個(gè)時(shí)間窗口。故用戶可見的時(shí)間窗口無變化。
- 在超級(jí)表的查詢中,已經(jīng)有歸屬于不同時(shí)間線的相同時(shí)間戳的查詢,增加了 primary key 以后,用戶可見表現(xiàn)層面無任何變化。
2.4.4 查詢函數(shù)
類別 | 函數(shù)名 | 是否變化 |
數(shù)據(jù)函數(shù) | ABS | 無影響 |
ACOS | 無影響 | |
ASIN | 無影響 | |
ATAN | 無影響 | |
CEIL | 無影響 | |
COS | 無影響 | |
FLOOR | 無影響 | |
LOG | 無影響 | |
POW | 無影響 | |
ROUND | 無影響 | |
SIN | 無影響 | |
SQRT | 無影響 | |
TAN | 無影響 | |
字符串函數(shù) | CHAR_LENGTH | 無影響 |
CONCAT | 無影響 | |
CONCAT_WS | 無影響 | |
LENGTH | 無影響 | |
LOWER | 無影響 | |
LTRIM | 無影響 | |
RTRIM | 無影響 | |
SUBSTR | 無影響 | |
UPPER | 無影響 | |
時(shí)間和日期函數(shù) | TIMEDIFF | 無影響 |
TIMETRUNCATE | 無影響 | |
轉(zhuǎn)換函數(shù) | CAST | 無影響 |
TO_ISO8601 | 無影響 | |
TO_JSON | 無影響 | |
TO_UNIXTIMESTAMP | 無影響 | |
TO_CHAR | 無影響 | |
TO_TIMESTAMP | 無影響 | |
聚合函數(shù) | APERCENTILE | 無影響 |
AVG | 無影響 | |
COUNT | 無影響 | |
ELAPSED | 無影響 | |
LEASTSQUARES | 無影響 | |
SPREAD | 無影響 | |
STDDEV | 無影響 | |
SUM | 無影響 | |
HYPERLOGLOG | 無影響 | |
HISTOGRAM | 無影響 | |
PERCENTILE | 無影響 | |
選擇函數(shù) | BOTTOM | 無影響 |
FIRST | 有變化 | |
INTERP | 有變化 | |
LAST | 有變化 | |
LAST_ROW | 有變化 | |
MAX | 無影響 | |
MIN | 無影響 | |
MODE | 無影響 | |
SAMPLE | 無影響 | |
TAIL | 無影響 | |
TOP | 無影響 | |
UNIQUE | 有變化 | |
時(shí)序數(shù)據(jù)特有函數(shù) | CSUM | 無影響 |
DERIVATIVE | 有變化 | |
DIFF | 有變化 | |
IRATE | 有變化 | |
MAVG | 無影響 | |
STATECOUNT | 無影響 | |
STATEDURATION | 無影響 | |
TWA | 有變化 |
變化的函數(shù)行為變化如下:
1. Interp
Interp 函數(shù)返回設(shè)定時(shí)間點(diǎn) T 0 的插值(斷面)數(shù)據(jù),其前置時(shí)間戳 Tprev(小于 T0的最大時(shí)間戳)或后置時(shí)間戳Tnxt(大于T0的最小時(shí)間戳)可能有重復(fù)時(shí)間,并且其對(duì)應(yīng)的數(shù)值不同。
進(jìn)行插值計(jì)算時(shí),前置時(shí)間戳 Tprev 或后置時(shí)間戳 Tnxt 均只使用首次出現(xiàn)的記錄進(jìn)行計(jì)算,丟棄其后出現(xiàn)的相同時(shí)間戳不同主鍵的記錄。
首次出現(xiàn)的定義:對(duì)于任一時(shí)間戳Tx,在按照升序返回的數(shù)據(jù)記錄中,(同一個(gè)表中數(shù)據(jù))第一條 Tx 的記錄即為首次出現(xiàn)記錄。降序返回的數(shù)據(jù)記錄中(同一個(gè)表中數(shù)據(jù))Tx 最后一次出現(xiàn)的記錄為首次出現(xiàn)。
需要注意,首次出現(xiàn)的判定只針對(duì)同一個(gè)表,對(duì)于超級(jí)表下的不同的表,無首次出現(xiàn)的判定。
2. FIRST
First 返回時(shí)間戳最小的記錄。對(duì)于同一個(gè)表中具有相同(最小)時(shí)間戳不同主鍵的情況,返回該表中具有該時(shí)間戳的所有記錄中首次出現(xiàn)的記錄。
首次出現(xiàn)定義同上。
超級(jí)表查詢中,在完成上述邏輯以后,還需要對(duì)來自不同表的時(shí)間戳進(jìn)行比較和取舍,針對(duì)來自不同vnode的記錄,如果 ts 相同需要進(jìn)行 primary key 的比較。因此 first 函數(shù)返回的全局最小的(ts + primary key) 最早的結(jié)果。
3. LAST
Last 返回時(shí)間戳最大的記錄。對(duì)于同一個(gè)表中具有相同(最大)時(shí)間戳不同主鍵的情況,返回該表中具有該時(shí)間戳的所有記錄中末次出現(xiàn)的記錄。
末次出現(xiàn)定義對(duì)應(yīng)于首次出現(xiàn)的定義。
針對(duì)超級(jí)表跨 vnode 查詢返回的結(jié)果,其判定邏輯于 FIRST 函數(shù)處理邏輯相同,需要同時(shí)比較 ts + primary key
4. LAST_ROW
與 last 函數(shù)相同。
5. UNIQUE
Unique 返回任一時(shí)間戳第一次出現(xiàn)的記錄。對(duì)于同一個(gè)表中的記錄,只返回首次出現(xiàn)的記錄。不同子表中的相同時(shí)間戳記錄,判定邏輯不變。
首次出現(xiàn)定義同上。
6. DERIVATIVE
同一個(gè)子表中的記錄,使用首次出現(xiàn)記錄進(jìn)行計(jì)算,忽略后續(xù)出現(xiàn)的相同時(shí)間戳不同主鍵的記錄。
首次出現(xiàn)定義同上。
7. DIFF
同一個(gè)子表中的記錄,使用首次出現(xiàn)記錄進(jìn)行計(jì)算,忽略后續(xù)出現(xiàn)的相同時(shí)間戳不同主鍵的記錄。
首次出現(xiàn)定義同上。
8. IRATE
同 derivative 函數(shù)處理邏輯相同。
9. TWA
同一個(gè)子表中數(shù)據(jù)進(jìn)行窗口邊界插值的時(shí)候,均使用首次出現(xiàn)記錄進(jìn)行插值計(jì)算返回結(jié)果。非首次出現(xiàn)記錄不參與計(jì)算。
首次出現(xiàn)定義同上。
10. show create
Show create
返回創(chuàng)建(超級(jí))表的SQL 語句,對(duì)于有 primary key 的(超級(jí))表,相應(yīng)的 SQL 語句有變化
11. DESC <table_name>
DESC 獲取 (超級(jí))表的 schema 信息,返回的結(jié)果中,需要標(biāo)記第二列(primary key 只能為第二列)是否是 primary key 列。
12. INSERT INTO <table_name> SELECT
會(huì)進(jìn)行符合性檢查,具有 primary key 的(超級(jí))表的不能向無 primary key 的表中寫入數(shù)據(jù)。無 primary key 的表可以向具有 primary key 的表寫入數(shù)據(jù)。
向 primary key 的表寫入數(shù)據(jù)的時(shí)候,要求 primary key 列必須非 NULL。
2.4.5 查詢子句
序號(hào) | 子句 | 行為變化 |
1 | 比較表達(dá)式/條件子句 | 無影響 |
2 | fill 子句 | 無影響 |
3 | 窗口子句 | 無影響 |
4 | group by 子句 | 無影響 |
5 | partition by 子句 | 無影響 |
6 | join 查詢 | 無影響 |
7 | Distinct 子句 | 無影響 |
8 | union子句 | 無影響 |
9 | slimit子句 | 無影響 |
10 | limit子句 | 無影響 |
11 | order by子句 | 無影響 |
12 | having子句 | 無影響 |
13 | range子句 | 無影響 |
14 | every子句 | 無影響 |
15 | 子查詢 | 無影響 |
2.5 流計(jì)算
2.5.1 流計(jì)算窗口
對(duì)我們所支持的窗口類型,即 Interval、Session窗口,如果數(shù)據(jù)源表是復(fù)合主鍵,數(shù)據(jù)先按時(shí)間戳排序,時(shí)間戳相同的,再按復(fù)合主鍵排序,然后才是其他列排序。所以復(fù)合主鍵場(chǎng)景,流計(jì)算當(dāng)前的設(shè)計(jì)和實(shí)現(xiàn)能夠透明處理,符合流計(jì)算窗口當(dāng)前的預(yù)期。存儲(chǔ)流計(jì)算結(jié)果的表是復(fù)合主鍵,則Interval、Session 窗口輸出結(jié)果時(shí),需要按照時(shí)間戳和復(fù)合主鍵排序。
流計(jì)算對(duì)于亂序數(shù)據(jù)的界定方式:當(dāng)前這批寫入的數(shù)據(jù),與之前寫入的數(shù)據(jù)做對(duì)比。窗口計(jì)算要求數(shù)據(jù)按時(shí)間戳有序,只是要求當(dāng)前這批數(shù)據(jù),這個(gè)是局部的,并不是要求數(shù)據(jù)源的全部數(shù)據(jù)有序。
2.5.2 創(chuàng)建流計(jì)算
需要考慮存儲(chǔ)流計(jì)算結(jié)果的表。對(duì)于自動(dòng)創(chuàng)建超級(jí)表場(chǎng)景,需要提供復(fù)合主鍵的信息。新增語法,在創(chuàng)建流計(jì)算的SQL中,顯式指定復(fù)合主鍵信息,即流計(jì)算結(jié)果中,哪些列是復(fù)合主鍵。對(duì)于寫入已存在超級(jí)表,通過元數(shù)據(jù)能夠獲取復(fù)合主鍵的信息,不需要SQL中指定。
語法如下:
CREATE STREAM [IF NOT EXISTS] stream_name [stream_options] INTO stb_name[(field1_name, field2_name [PRIMARY KEY], field3_name, ...)] [TAGS (create_definition [, create_definition] ...)] SUBTABLE(expression) AS subquery
PRIMARY KEY 使用規(guī)則和限制與建表SQL相同。
2.5.3 流計(jì)算中不支持的場(chǎng)景
由于需要按照 PK 刪除 已經(jīng)生成的記錄。因此,不支持狀態(tài)窗口、事件窗口、計(jì)數(shù)窗口在有 pk 的表上進(jìn)行計(jì)算。對(duì)于全是標(biāo)量函數(shù)的流計(jì)算,不支持?jǐn)?shù)據(jù)源是復(fù)合主鍵,且目標(biāo)表不是復(fù)合主鍵。
2.6 訂閱
2.6.1?接口變更
-
tmq_get_json_meta(獲取meta信息的 json 描述)
????該接口內(nèi)部創(chuàng)建表數(shù)據(jù)結(jié)構(gòu)里增加列是否是復(fù)合主鍵參數(shù)("isPrimarykey":true)。已在文檔里更新: https://jira.taosdata.com:18090/pages/viewpage.action?pageId=158206215
-
tmq_get_raw 接口返回的 raw data 做了升級(jí),請(qǐng)查看文檔 數(shù)據(jù)訂閱結(jié)果序列化方案
2.6.2 其它接口無變更
2.7 Last 緩存
-
cache_model: none,返回最大的時(shí)間戳和該時(shí)間戳下最大的主鍵所對(duì)應(yīng)的行或值
-
cache_mode: last_value, last_row, both,查詢行為受緩存更新規(guī)則影響,更新規(guī)則如下:
?????緩存的更新粒度仍然是表級(jí)別。在主時(shí)間戳列相同情況下,主鍵列按大小順序取最大值。即在更新緩存時(shí),新到達(dá)的數(shù)據(jù)與當(dāng)前 last 緩存中的數(shù)據(jù)相比,如果時(shí)間戳更大或時(shí)間戳相同但主鍵值更大則更新緩存,否則不更新緩存。
3. 性能影響
3.1 寫入性能
-
非重復(fù)時(shí)間戳:在沒有任何兩條記錄時(shí)間戳相同的情況下,其寫入性能與未引入 primary key 相比完全相同
-
有重復(fù)時(shí)間戳的場(chǎng)景:在極端情況下,時(shí)間戳全部相同,而 primary key 單調(diào)遞增,預(yù)估這種場(chǎng)景下寫入性能下降 50%,原因是要進(jìn)行兩次鍵值比較。
-
純亂序數(shù)據(jù)寫入:即任意一行記錄的時(shí)間戳和 primary key 都有可能小于之前已經(jīng)寫入的部分記錄,這種情況下仍舊無法預(yù)估性能下降的比例。原則亂序程度越高,性能下降越明顯
3.2 查詢性能
3.2.1 數(shù)據(jù)讀取
讀取過程中,在merge階段需要同時(shí)比較 ts 和 primary key column,因此 merge 過程會(huì)消耗更多的 CPU,記錄合并過程會(huì)出現(xiàn)明顯地性能下降。
合并過程是在 tsdb 完成,因此所有的查詢均受影響(只使用 head 文件 和 SMA 索引的查詢除外)。性能受到的影響程度受 key長(zhǎng)度、數(shù)據(jù)寫入模式、數(shù)據(jù)在文件中物理分布、數(shù)據(jù)重復(fù)比例、數(shù)據(jù)讀取開銷在整個(gè)查詢過程中資源開銷占比等諸多因素共同影響,無法簡(jiǎn)單評(píng)估性能下降的程度。
3.2.2 不同類型查詢性能表現(xiàn)
在排除數(shù)據(jù)讀取性能降低的場(chǎng)景下,對(duì)于非分組類型的查詢(沒有 partition by 和 group by 子句),沒有明顯的變化。
4. 兼容性
1. 不會(huì)對(duì)已存在的數(shù)據(jù)產(chǎn)生影響,數(shù)據(jù)不支持版本回退,因?yàn)榈桶姹咀R(shí)別不出復(fù)合主鍵。
2. 流計(jì)算會(huì)有影響。需要?jiǎng)h除刪除流計(jì)算才能進(jìn)行升級(jí)。
5. 約束和限制
-
只允許額外指定除時(shí)間戳以外的一列作為主鍵
-
支持定長(zhǎng)和變長(zhǎng)類數(shù)據(jù)類型,暫定支持非浮點(diǎn)數(shù)及 varchar。
-
主鍵與時(shí)間戳列一樣,不允許缺省或?yàn)?NULL
-
主鍵列不允許 alter 或 drop 等操作
-
已建無主鍵列的表不可以通過 alter 語句添加主鍵列
-
不支持對(duì)主鍵列的范圍刪除
6. 總結(jié)
本章主要介紹了新功能復(fù)合主鍵的對(duì)外接口使用、影響的功能及函數(shù)內(nèi)部技術(shù)實(shí)現(xiàn),受約條件等,幫助技術(shù)開發(fā)人員更好了解及使用此功能。