基本介紹
- 中文名:高速快取資料庫
- 外文名:STVM
- 1:高速離線快取資料庫
- 2:最快快取資料庫沒有之一
STVM,定義,性能,支持語言,欄位類型,使用手冊,開發流程,創建表,操作表(查詢單記錄),操作表(查詢多條記錄),操作表(新增記錄),操作表(刪除記錄),操作表(修改記錄),
STVM
STVM(truck of Virtual memory table)是一個開源的使用ANSI C語言編寫、支持本地API調用和網路調用,全表數據基於IPC共享記憶體方式存儲,
基於C語言struck結構定義記錄行,RB-Tree和hash作為主要算法的記憶體資料庫,是一款介於SQL和NOSQL之間的一款高速快取資料庫。
由於數據全部存儲在記憶體中,相比較其他類型的快取,運行速度之快可想而知。
定義
stvm是一款其介於介於SQL和NOSQL,擁有以下主要特點
支持SQL基本語法(本版本支持insert、update、delete、select、group order、count,first,游標)功能。
支持序列
支持唯一索引、查詢索引和組合索引(組合索引不必考慮索引欄位先後)
支持條件動態查詢
內置記錄點擊量
集群、主-子分布同步。
事務功能(假性事務)
數據持久性,進程異常退出,不會導致數據丟失,除非系統宕機。
支持網路API和函式API, 支持多執行緒、多進程等等
內置數據版本,維護數據一致安全。
多機集群,數據分區
當然也有幾點缺陷,索引長度限制目前版本64位,修改長度需編譯項目、啟動後不能修改表欄位(ddl語句),不能聯表查詢。
stvm是一款高速快取資料庫,表欄位定義來源與C語言STRUCK,動態條件賦值只需要對結構體成員賦值即為查詢條件。
整個操作提供特定API訪問,減少解析SQL和欄位的時間。
全表數據分3個區(表頭區、索引區、數據區),並且全部存儲在一塊記憶體中。
每張表定義一個資料庫塊,每張表擁有自己讀寫鎖,支持執行緒。
預留拓展表空間參數,但效率會降低擴展個數倍
性能
在相同環境在,用本機API訪問對單標操作是redis的30倍以上。網路api也快1.5倍以上。
比fastdb快倍10左右。
其他沒逐一測試。
支持語言
C | C++ | Java | …… |
支持 | 支持 | 待支持 |
欄位類型
欄位類型有LONG,CHAR,DOUB(對應整型、字元型、浮點型)
行記錄建議不要超過500KB
為了避免記憶體的浪費,唯一索引和查詢索引最多各一組。
使用手冊
啟動環境變數:
TVMDBD=/home/stvm/tvmdb 指向stvm工作目錄
TVMCFG=/home/stvm/tvmdb/.tvm.run 啟動參數
配置完成後,stvm -w採用預設啟動參數進去本機模式。
如果集群模式請配置 stvm.conf,然後用stvm -c stvm.conf編譯配置檔案即可。
STVM對外提供2個開發運維工具stvm和調試工具detvm。
stvm -w啟動啟動
stvm -s停止系統
STVM也提供一個類型sqlpuls類型簡單工具,輸入:stvm SQL進入SQL界面,該工具僅僅用來運維調試使用。
stvm dom --進入域的維護
開發流程
創建表
// 定義表序號
#define TBL_USER_INFO 10
必須用C定義STRUCK:
typedef struct __TBL_USER_INFO { long acct_id; char user_no[21]; char user_type[2]; char user_nm[81]; char user_addr[161]; char user_phone[31]; }dbUser;
定義創建表函式
CREATE lCreateUserInfo() { DEFINE(TBL_USER_INFO, "TBL_USER_INFO", "", dbUser) FIELD(dbUser, acct_id, "acct_id", FIELD_LONG) FIELD(dbUser, user_no, "user_no", FIELD_CHAR) FIELD(dbUser, user_type, "user_type", FIELD_CHAR) FIELD(dbUser, user_nm, "user_nm", FIELD_CHAR) FIELD(dbUser, user_addr, "user_addr", FIELD_CHAR) FIELD(dbUser, user_phone, "user_phone", FIELD_CHAR) CREATE_IDX(NORMAL) // 創建查詢索引 IDX_FIELD(dbUser, acct_id, FIELD_LONG) CREATE_IDX(UNQIUE) // 創建唯一索引 IDX_FIELD(dbUser, user_no, FIELD_CHAR) IDX_FIELD(dbUser, user_type, FIELD_CHAR) FINISH }
調用api:
lCreateTable(pstSavm, TBL_USER_INFO, 100000, lCreateUserInfo)完成對TBL_USER_INFO表的創建。
其中pstSavm為執行緒句柄
TBL_USER_INFO 創建的表序號,
100000初始化記憶體記錄空間條數。
lCreateUserInfo創建表定義函式。
調用成功則返回RC_SUCC, 失敗返回RC_FAIL, 失敗可調用pstSavm->m_lErrno獲取處理失敗錯誤碼,sGetTError(pstSavm->m_lErrno)獲取錯誤信息。
操作表(查詢單記錄)
dbUser stUser;SATvm *pstSavm = (SATvm *)pGetSATvm();// 初始化TBL_USER_INFO表,每張表都需要初始化一次, 對於表重建後,需要重新初始化一次。if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)){ fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); return ;}conditinit(pstSavm, stUser, TBL_USER_INFO); // 綁定變數numberset(pstSavm, stUser, user_type, "1"); // 查詢條件賦值stringset(pstSavm, stUser, user_no, "20180223"); // 查詢條件賦值if(RC_SUCC != lSelect(pstSavm, (void *)&stUser)) // 單條記錄查詢{ fprintf(stderr, "Select錯誤ep:%d, err:(%d)(%s)\n", pstSavm->m_lEType, pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); return ;}fprintf(stdout, "acct_id:%ld, user_no:%s, user_type:%s, user_nm:%s, user_addr:%s, user_phone:%s\n", stUser.acct_id, stUser.user_no, stUser.user_type, stUser.user_nm, stUser.user_addr, stUser.user_phone);
操作表(查詢多條記錄)
size_t i = 0, lOut; dbUser *pstUser; SATvm *pstSavm = (SATvm *)pGetSATvm();// 初始化TBL_USER_INFO表,每張表都需要初始化一次, 對於表重建後,需要重新初始化一次。 if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) { fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); return ; } conditinit(pstSavm, stUser, TBL_USER_INFO); // 綁定變數 numberset(pstSavm, stUser, user_type, "1"); // 查詢條件賦值 stringset(pstSavm, stUser, user_no, "20180223"); // 查詢條件賦值 if(RC_SUCC != lQuery(pstSavm, &lOut, (void **)&pstUser)) // 批量查詢查詢 { fprintf(stderr, "Select錯誤ep:%d, err:(%d)(%s)\n", pstSavm->m_lEType, pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); return ; } for(i = 0; i < lOut; i ++) { fprintf(stdout, "acct_id:%ld, user_no:%s, user_type:%s, user_nm:%s, user_addr:%s, user_phone:%s\n", pstUser[i].acct_id, pstUser[i].user_no, pstUser[i].user_type, pstUser[i].user_nm, pstUser[i].user_addr, pstUser[i].user_phone); }
操作表(新增記錄)
dbUser stUser; SATvm *pstSavm = (SATvm *)pGetSATvm(); // 初始化TBL_USER_INFO表,每張表都需要初始化一次, 對於表重建後,需要重新初始化一次。 if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) { fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); return ; } stUser.acct_id = 10021; // 對結構體賦值 strcpy(stUser.user_no, "20180223"); // 對結構體賦值 strcpy(stUser.user_type, "1"); // 對結構體賦值 insertinit(pstSavm, stUser, TBL_USER_INFO); // 綁定變數 if(RC_SUCC != lInsert(pstSavm)) // 插入記錄 { fprintf(stderr, "Select錯誤ep:%d, err:(%d)(%s)\n", pstSavm->m_lEType, pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); return ; }
操作表(刪除記錄)
dbUser stUser; SATvm *pstSavm = (SATvm *)pGetSATvm(); // 初始化TBL_USER_INFO表,每張表都需要初始化一次, 對於表重建後,需要重新初始化一次。 if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) { fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); return ; } conditinit(pstSavm, stAct, TBL_USER_INFO) // 對結構體賦值 numberset(pstSavm, stUser, user_type, "1"); // 查詢條件賦值 stringset(pstSavm, stUser, user_no, "20180223"); // 查詢條件賦值 if(RC_SUCC != lDelete(pstSavm)) // 刪除記錄 { fprintf(stderr, "Delete err:(%d)(%s)\n", pstSavm->m_lEType, pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); return ; }
操作表(修改記錄)
dbUser stUser, stUpd; SATvm *pstSavm = (SATvm *)pGetSATvm(); if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) { fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); return ; } updateinit(stUpd); conditinit(pstSavm, stUser, TBL_USER_INFO) // 綁定變數 numberset(pstSavm, stUser, user_type, "1"); // 查詢條件賦值 stringset(pstSavm, stUser, user_no, "20180223"); // 查詢條件賦值 stringupd(pstSavm, stUpd, user_phone, "18691128912"); if(RC_SUCC != lUpdate(pstSavm, (void *)&stUpd)) { fprintf(stderr, "Update err:(%d)(%s), (%ld)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno), lGetEffect()); return ; }
其他函式lTruncate、lCount、lExtreme、lGroup, 和網路API如lTvmDelete、lTvmInsert、lTvmSelect、lTvmUpdate、lTvmTruncate、lTvmCount、lTvmExtreme、lTvmGroup、lTvmQuery、不做一一枚舉。