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