一、為什么不用key-value型數(shù)據(jù)庫實現(xiàn)關(guān)系型數(shù)據(jù)庫
TiDB / CockroachDB 都是基于 KV 模型做的分布式關(guān)系型數(shù)據(jù)庫。TiDB 實際上是構(gòu)建在 TiKV + pd 這一分布式 KV 存儲上的數(shù)據(jù)庫。所有表都以行的形式存在 KV 數(shù)據(jù)庫里。
e.g. TiDB 表 a 的某一行,主鍵為 b,就會變成 TiKV 里的一個 KV pair。key 為 table id + primary key, value 為這一行所有列的值。
在繼續(xù)回答之前先定義一下 KV 型數(shù)據(jù)庫,區(qū)分開存儲引擎和基于 KV 的關(guān)系型數(shù)據(jù)庫。RocksDB 是 KV 型數(shù)據(jù)庫(或者說單機 KV 存儲引擎);TiDB 是基于 KV 存儲引擎做的分布式關(guān)系型數(shù)據(jù)庫。
至于“日常業(yè)務(wù)中的很多簡單查詢”是否用基于 KV 的數(shù)據(jù)庫更好,可以先從存儲引擎的角度看。
從存儲引擎的角度來講,不管是 MySQL InnoDB 的 B+ 樹,還是基于 LSM-Tree KV 存儲引擎的 MyRocks / CockroachDB / TiDB,跑一個 SELECT * WHERE pk = 1; 讀的路徑應(yīng)該不會有太大的區(qū)別,無非是根據(jù) sort key 定位對應(yīng)的 page / block 然后把一行撈出來,所以沒有好壞之分。
與此同時,如果這些“簡單查詢”就是直接跑在 KV 存儲引擎上的(比如問題中提到的 RediSQL),只是簡單地把 SQL 翻譯成了 KV 操作,還需要考慮對表的操作是否有事務(wù)隔離性的要求。即使是“簡單的”操作,e.g.
UPDATE x = x + 1;
也需要考慮事務(wù)的隔離性。對于 KV 存儲引擎來講,大多數(shù)引擎只提供點查、刪除、scan 的接口,開發(fā)者要在上面自己實現(xiàn)一層事務(wù)層。特別是在分布式場景下,這個事情就有點復(fù)雜了,和分布式關(guān)系型數(shù)據(jù)庫所面臨的問題是一樣的。
所以講到底,如果要在 KV 引擎上實現(xiàn)關(guān)系型數(shù)據(jù)庫,即使只支持簡單的 query,也需要處理很多 KV 引擎本身沒有考慮到的事情,比如事務(wù)、持久化(對于 in-memory engine 來說)等等。
延伸閱讀:
二、MongoDB是什么
非關(guān)系型數(shù)據(jù)庫(nosql ),屬于文檔型數(shù)據(jù)庫。MongoDB采用類JSON的documents來存儲數(shù)據(jù)。數(shù)據(jù)結(jié)構(gòu)由鍵值(key=>value)對組成。
MongoDB采用動態(tài)數(shù)據(jù)模型schema,這意味著不需要預(yù)先定義表的數(shù)據(jù)類型和字段名。當(dāng)MongoDB需要更新文檔documents的時候,可以輕松增加新的字段名或者刪除舊的字段。MongoDB讓數(shù)據(jù)結(jié)構(gòu)更加層級化,因而存儲數(shù)組等復(fù)雜數(shù)據(jù)結(jié)構(gòu)。 在同一個集合collection中,文檔document對字段也沒有強約束,因此更容易設(shè)計差異化的數(shù)據(jù)結(jié)構(gòu)。