STVM

STVM(truck of Virtual memory table)是一個開源的使用ANSI C語言編寫、支持本地API調用和網路調用,全表數據基於IPC共享記憶體方式存儲,基於C語言struck結構定義記錄行,RB-Tree和hash作為主要算法的記憶體資料庫,是一款介於SQL和NOSQL之間的一款高速快取資料庫。

基本介紹

  • 中文名:高速快取資料庫
  • 外文名:STVM
基本簡介,定義,性能,支持語言,欄位類型,使用手冊,開發流程,

基本簡介

由於數據全部存儲在記憶體中,相比較其他類型的快取,運行速度之快可想而知。

定義

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、不做一一枚舉。

相關詞條

熱門詞條

聯絡我們