【TcaplusDB知識庫】條件過濾說明與更新
1. 介紹
-
條件查詢 : 對單條記錄或批量記錄查詢時,可指定記錄級別的過濾條件,要求返回記錄滿足條件。
-
條件更新 : 對單條記錄或批量記錄修改或刪除時,可指定記錄級別的過濾條件,只有條件滿足時才會執行變更。
-
陣列更新 : 陣列型別的欄位(如 protobuf 中的 repeated 欄位),支援對陣列中元素進行增刪改操作,可以只處理滿足某些條件過濾的元素。
-
陣列查詢 : 陣列型別的欄位(如 protobuf 中的 repeated 欄位),查詢陣列中返回滿足過濾條件的或者某些下標範圍內的資料,而不是完整的記錄。
generic 表和 list 表都支援條件操作。
2. 示例表定義
這裡分別定義兩種型別的表,用於本章節示例,為了更直觀說明條件過濾和更新。本章節以protobuf協議作為示例,但TDR協議同樣支援條件過濾和更新,使用類似。
-
Generic 表
syntax = "proto3";
package myTcaplusTable;
import "tcaplusservice.optionv1.proto";
message user {
option( tcaplusservice. tcaplus_primary_key) = "id,name";
option( tcaplusservice. tcaplus_index) = "name_index(name)";
message mail {
string title = 1;
string content = 2;
}
int32 id = 1;
string name = 2;
int32 rank = 3;
repeated int64 gameids = 4;
repeated mail mailbox = 5;
}
-
List 表
syntax = "proto3";
package myTcaplusTable;
import "tcaplusservice.optionv1.proto";
message list_user {
option( tcaplusservice. tcaplus_primary_key) = "id,name";
option( tcaplusservice. tcaplus_customattr) = "TableType=SORTLIST;ListNum=1024;SortField=rank";
message mail {
string title = 1;
string content = 2;
}
int32 id = 1;
string name = 2;
int32 rank = 3;
repeated int64 gameids = 4;
repeated mail mailbox = 5;
}
3. 條件過濾說明
支援記錄級別的條件過濾,只有滿足條件,才對指定的(一個或多個)記錄進行操作,包括對記錄修改、刪除或查詢等。
3.1 解決什麼問題
若沒有條件過濾,對於 generic 表,通過主鍵查詢或操作一個記錄,若對應主鍵不存在,則返回錯誤碼 TXHDB_ERR_RECORD_NOT_EXIST。
而條件則在這基礎上再加一層過濾,對於 generic 表,主鍵 key 對應存在基礎上,必須條件滿足才能查詢或操作對應的記錄,否則返回錯誤碼 COMMON_ERR_CONDITION_NOT_MATCHED。
key + condition,相當於 SQL 中的
where
語句,雖然能力比 SQL 還差不少,但已經提供一定程度的靈活能力。 特別是對於“讀判斷-然後寫”的原子操作場景特別有用,條件更新的初衷就是解決這個問題的。
例如,對於 user 表,若 gameids 陣列不包含 101 這個元素,那麼在該陣列插入 101,那麼應用程式碼會寫成如下
user u;
// 設定主鍵
u. set_id( 1);
u. set_name( "a");
int ret = api. Get( & u);
// ...
if ( ! Find( u. gameids(), 101)) // Find是應用實現的函式,在陣列中找是否存在某元素
{
u. add_gameids( 101);
ret = api. Set( & u);
// ...
}
上述程式碼存在幾個問題
-
應用端和服務端存在多處互動,先 Get 再 Set。
-
若 user 結構較大,那麼這個流程中涉及的序列化、反序列帶來不必要的開銷較大。
-
最嚴重 的是,Get + Set 兩次互動,這個邏輯不是原子的,若應用端存在多個這樣流程併發,可能重複插入 101,這造成邏輯錯誤。由於 TcaplusDB 還不支援事務,應用解決該問題比較繁瑣。
針對上述問題,條件更新可以解決一些互動多、非原子等問題,示例條件操作程式碼如下:
user u;
// 設定主鍵
u. set_id( 1);
u. set_name( "a");
// 先判斷gameids是否已經包含101,若不存在(條件不滿足)再插入101
int ret = api. UpdateItem( & u, "PUSH gameids#[-1][$ = 101]", "gameids NOT CONTAINS($==101)");
if ( ret == COMMON_ERR_CONDITION_NOT_MATCHED) // 條件不滿足,說明gameids已經存在101了
{
// ...
}
上述程式碼,
"gameids NOT CONTAINS($==101)"
就是過濾條件,而
"PUSH gameids#[-1][$ = 101]"
是陣列操作語句,後文介紹,這裡指在 gameids 陣列尾部插入 101。
3.2 條件過濾介面說明
TcaplusDB 提供的一些 protobuf API 新增了
const std::string &condition
入參,用於指定過濾條件,支援 condition 的介面以及新增的錯誤碼詳見後文的附錄。
一些介面的使用示例如下,更多的示例可見詳細 example。
// tcaplus_coroutine_pb_api.h
int Set(:: google::protobuf::Message * msg, const std::string & operation = "", const std::string & condition = "");
int FieldInc( const std::set < std::string > & dottedpaths, :: google::protobuf::Message * msg, const std::string & operation = "", const std::string & condition = "");
int Traverse(:: google::protobuf::Message * msg, const std::string & condition, TcaplusTraverseCallback * cb);
// example.cpp
user u;
// 設定主鍵
u. set_id( 1);
u. set_name( "a");
// 設定其他內容
// ...
// 當rank>100,才執行Set操作,若條件不滿足會返回對應的錯誤碼
int ret = api. Set( & u, "", "rank > 100");
if ( ret == COMMON_ERR_CONDITION_NOT_MATCHED) { ... } // 條件不滿足的情況
// 設定遞增的步長
u. set_rank( 1);
// 當rank達到上限100之後,不在對rank遞增,否則 +1
std::set < std::string > dottedpaths;
dottedpaths. insert( "rank");
ret = api. FieldInc( dottedpaths, & u, "", "rank < 100");
// 遍歷2021-01-01年之後修改過的記錄,這裡$.LastAccessTime是記錄的內建屬性,表示記錄的最後更新時間
int ret = api. Traverse( & u, "$.LastAccessTime >= \"2021-01-01\"", & traverseCallback);
3.3 條件過濾語法說明
過濾條件是類 SQL 的 where 語句的語法,已支援以下幾種過濾能力
-
比較,如
rank > 1
,比較符有>, >=, <, <=, =, ==, !=
,在比較的上下文中,=
也是相等比較,而在其他語境下可能是賦值符號 。 -
邏輯運算,如
rank > 1 AND rank < 10
,運算子有AND, OR, NOT
。 -
位運算,僅支援“與”,如
filter & 8
,當從低往高的第三位為 1 時,該表示式為 true。 -
CONTAINS
和NOT CONTAINS
,即判斷是否包含,如"mailbox CONTAINS(title == \"tcaplus\")"
表示要求 mailbox 包含一個 title 等於"tcaplus"的元素。CONTAINS 括號中可以是更復雜的子條件。 -
內建屬性
$.LastAccessTime
,該內建屬性表示記錄的最後更新時間,最小精度為秒,可用於和字串表示的時間進行比較,如"2021"、"2021-01-01"或"2021-01-01 00:00:00"。 -
當前陣列元素的引用
$
,如,"gameids NOT CONTAINS($==101)"
。
完整語法如下
condition_expr :: =
array CONTAINS '(' condition ')'
| array NOT CONTAINS '(' condition ')'
| condition
condition :: =
operand
| operand comparator operand
| condition AND condition
| condition OR condition
| NOT condition
| operand bitwise_op operand
comparator :: =
==
| =
| <
| >
| <=
| >=
| !=
bitwise_op :: =
&
array :: =
identifier
operand :: =
identifier
| number
| string
| $
| $. LastAccessTime
-
語法說明
-
identifier : 一個合法的標識名稱,在這裡是欄位名或欄位名路徑,如
name
或mail.title
。 -
number : 整型或浮點數,不支援大整數。
-
string : 雙引號或者單引號括起來的字串。
-
-
比較
-
不同精度的整型或浮點型的數值都是可以相互比較的,這和 C++語言中是一致的,例如 int16 和 int32 比較,前者的型別會被提升之後再比較,整型和浮點比較,整型則會先被提升為浮點型。
-
int 和 uint 可比較,會先比較符號位。
-
浮點型的等值會有精度偏差。
-
字串也是可比較,按照字母字典序,這和 C++中的 std::string 的比較行為是一致的。
-
數值型別和字串直接不可比較。
-
-
操作符優先順序
-
條件表示式 condition 中,操作符優先順序,從高到低為
comparator NOT AND OR
,例如"a==1 OR a>10 AND a<20"
,會先計算 AND 的結果再計算 OR。 -
當然可以使用括號來分隔條件表示式,例如
"(a==1 OR a>10) AND a<20"
則就先計算 OR。
-
3.4 效能優化建議
條件過濾的效能和 1)條件表示式、2)表的模式 有關,滿足以下規則時,有針對性的效能優化(僅供參考,內部實現可能會調整):
-
當條件表示式只用到 key 欄位(包括主鍵和 index 欄位)和記錄的屬性欄位(如$.LastAccessTime),僅通過記錄的主鍵或索引即可進行判斷,無需從儲存引擎讀取全量資料。
-
對於 SortList 表,當條件表示式只使用了 sort 欄位,也有效能優化。
-
對於 SortList 表,表定義的排序欄位只有一個,且條件表示式是簡單的二元比較(如
"field >= 1"
和"field == 1"
等),有更好的效能優化,即使用二分查詢。
TcaplusDB是騰訊出品的分散式NoSQL資料庫,儲存和排程的程式碼完全自研。具備快取+落地融合架構、PB級儲存、毫秒級時延、無損水平擴充套件和複雜資料結構等特性。同時具備豐富的生態、便捷的遷移、極低的運維成本和五個九高可用等特點。客戶覆蓋遊戲、網際網路、政務、金融、製造和物聯網等領域。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69982264/viewspace-2843733/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【TcaplusDB知識庫】TcaplusDB本地索引介紹索引
- 【TcaplusDB知識庫】什麼是TcaplusDB資料庫?資料庫
- 【TcaplusDB知識庫】TcaplusDB全域性索引介紹索引
- 條件過濾檢索
- openssh版本更新與說明 openssl版本更新與說明
- 【TcaplusDB知識庫】PB表 C++ 示例程式碼-更新資料C++
- [TcaplusDB知識庫]TcaplusDB客戶端及常用命令客戶端
- 資料庫知識點(5)——多列過濾資料庫
- [jQuery知識]jQuery之知識三-過濾器jQuery過濾器
- 【TcaplusDB知識庫】預設Schema表型別介紹型別
- 【TcaplusDB知識庫】如何對陣列進行操作陣列
- java8 多條件的filter過濾JavaFilter
- 《MySQL 入門教程》第 08 篇 過濾條件MySql
- Stream中filter過濾條件問題記錄Filter
- MySQL全面瓦解7:查詢的過濾條件MySql
- ORACLE SQL過濾條件是IS NULL or !=的優化OracleSQLNull優化
- MongoDB之資料查詢(where條件過濾)MongoDB
- JN專案-查詢條件過濾特殊字元字元
- 自定義 Azure Table storage 查詢過濾條件
- 【小知識】QueryWrapper迴圈or條件APP
- 34. 過濾條件、多表查詢、子查詢
- mysql (ICP) 索引條件下推對比ORACLE進行說明MySql索引Oracle
- 資料泵過濾匯出資料的where條件
- PJzhang: github與出口管制·說明條款Github
- [TcaplusDB知識庫]資料庫支撐底盤引擎計算層介紹資料庫
- mysql多條件過濾查詢之mysq高階查詢MySql
- 最佳化數倉業務檢視:過濾條件傳遞
- 關於 hibernate 邏輯刪除 預設查詢過濾條件問題(java set 條件)Java
- 卡爾曼濾波的原理說明
- 【TcaplusDB知識庫】PB表 C++ 示例程式碼-讀取資料C++
- 【TcaplusDB知識庫】PB表C++示例程式碼-刪除資料C++
- Vuejs基本知識(三)【語法簡寫說明】VueJS
- 『忘了再學』Shell基礎 — 28、AWK中條件表示式說明
- 洛必達法則的證明與可用條件
- 帶你讀 MySQL 原始碼:where 條件怎麼過濾記錄?MySql原始碼
- Linux下" >/dev/null 2>&1 "相關知識說明LinuxdevNull
- 8條專案管理知識庫,小白必看!專案管理
- SpamSieve for mac(郵件過濾器)Mac過濾器