數(shù)據(jù)模型與查詢語言

數(shù)據(jù)模型應(yīng)該是軟件開發(fā)中最重要的部分,它不僅對軟件編碼方式,而且對如何思考待解決的問題都有深遠(yuǎn)的影響.

數(shù)據(jù)模型

關(guān)系模型

在關(guān)系模型中,數(shù)據(jù)被組織成關(guān)系,在SQL中被稱為表.每個(gè)關(guān)系都是元組的無需集合.
優(yōu)點(diǎn):

  1. 存在模式的規(guī)范.關(guān)系模型中支持一系列范式,更好的組織數(shù)據(jù).
  2. 關(guān)系模型可以支持多對一,多對多的關(guān)系表示,只需要進(jìn)行join操作就行.
  3. 關(guān)系模型使用的查詢語言是聲明式的,開發(fā)者無需關(guān)系具體的執(zhí)行步驟.

缺點(diǎn):

  1. 關(guān)系和對象不是一一對應(yīng)的.在面向?qū)ο缶幊讨?應(yīng)用代碼中的對象需要與關(guān)系模型中的表,行,列進(jìn)行轉(zhuǎn)換,這里需要一個(gè)叫做ORM的中間層.
  2. 不支持?jǐn)?shù)據(jù)的嵌套,沒辦法滿足局部最優(yōu)性的優(yōu)化.

文檔數(shù)據(jù)庫模型

文檔數(shù)據(jù)庫是一種層次模型:在父記錄中保存了嵌套記錄(一對多的關(guān)系),而不是單獨(dú)保存在表中.
優(yōu)點(diǎn):

  1. 文檔數(shù)據(jù)庫對保存的數(shù)據(jù)沒有模式限制,但是包含隱式的模式.
  2. 文檔數(shù)據(jù)庫保存的數(shù)據(jù)可以直接映射為應(yīng)用代碼中使用的數(shù)據(jù)結(jié)構(gòu).
  3. 在訪問整個(gè)文檔中大部分?jǐn)?shù)據(jù)時(shí),具有局部性性能優(yōu)勢.
  4. 數(shù)據(jù)支持嵌套,可以通過引用指向其他數(shù)據(jù).
  5. 針對數(shù)據(jù)格式改變時(shí),只需要使用新格式生成新文檔,應(yīng)用程序處理讀取就文檔的情況就可以了.

缺點(diǎn):

  1. 不支持join操作,所以幾乎無法表示多對多的關(guān)系.
  2. 修改時(shí)會(huì)整個(gè)重寫文檔.如果文檔太大則有些浪費(fèi).

圖狀數(shù)據(jù)模型

如果大多是數(shù)據(jù)直接沒有什么關(guān)系,或者最多有一對多的關(guān)系,那么文檔模型是合適的.
如果數(shù)據(jù)之間大部分都存在關(guān)系,可以是一對多,多對多的關(guān)系,數(shù)據(jù)見關(guān)系比較簡單的時(shí)候可以使用關(guān)系模型.
如果數(shù)據(jù)間存在很復(fù)雜的關(guān)聯(lián)關(guān)系,那么使用圖數(shù)據(jù)模型就是很自然的事情.例如:社交網(wǎng)絡(luò),Web圖,地鐵圖等.
圖數(shù)據(jù)模型中包含兩個(gè)元素:頂點(diǎn),邊.所以有很多種圖數(shù)據(jù)模型存在.

圖數(shù)據(jù)模型優(yōu)點(diǎn):

  1. 任何頂點(diǎn)可以連接到其他任何頂點(diǎn).沒有模式限制.
  2. 給定一個(gè)頂點(diǎn)可以快速獲取它的出邊和入邊.
  3. 通過對不同類型的關(guān)系使用不同的標(biāo)簽,可以在單個(gè)圖中存儲多種不同類型的信息.

我們先看看屬性圖模型.

屬性圖模型
屬性圖模型中,每個(gè)頂點(diǎn)包括:

  1. 唯一標(biāo)志符.
  2. 出邊集合.
  3. 入邊集合.
  4. 屬性集合(KV對).

每個(gè)邊包括:

  1. 唯一標(biāo)志符.
  2. 邊開始的頂點(diǎn)(尾部頂點(diǎn)).
  3. 邊結(jié)束的頂點(diǎn)(頭部頂點(diǎn)).
  4. 描述兩個(gè)頂點(diǎn)間關(guān)系的標(biāo)簽.
  5. 屬性的集合(KV對).

三元存儲
三元存儲包含:主體,謂語,客體三部分.
主體是圖中的頂點(diǎn),客體則是下面兩種的一種:

  • 原始數(shù)據(jù)類型中的值.這種情況下謂語和客體相當(dāng)于主體屬性中的鍵值對.例如:(lucy, age, 33)
  • 圖中另一個(gè)頂點(diǎn).此時(shí),謂語為圖中的邊,主體為尾部頂點(diǎn),客體為頭部定點(diǎn).例如:(lucy, marriedTo, alain).

查詢語言

命令式

針對文檔型數(shù)據(jù)庫,由于數(shù)據(jù)的組織方式是樹狀結(jié)構(gòu),所以開發(fā)出來了命令式查詢語言CODASYL
記錄之間的鏈接不是外鍵的方式,而是類似于編程語言中的指針.訪問記錄的唯一方式是從根出發(fā),沿著相關(guān)的鏈接依次訪問. 即應(yīng)用程序需要管理完整的訪問路徑.
需要告訴計(jì)算機(jī)以特定的順序執(zhí)行某些操作.

聲明式

聲明式語言則只需要指定所需的數(shù)據(jù)模式,結(jié)果需要滿足什么條件,以及如何轉(zhuǎn)換數(shù)據(jù)就行了.不需要執(zhí)行查詢操作的每一個(gè)步驟. SQL就是典型的聲明式查詢語言.
使用聲明式查詢語言,可以將數(shù)據(jù)庫引擎的實(shí)現(xiàn)細(xì)節(jié)隱藏起來,使在查詢語句不改變的情況下,優(yōu)化數(shù)據(jù)庫成為可能.
聲明式語言支持并行執(zhí)行.命令式則需要處理更多的細(xì)節(jié).

mapReduce查詢

MapReduce是一種編程模型,用于在許多機(jī)器上處理海量的數(shù)據(jù).
MapReduce既不是命令式,也不是聲明式:查詢邏輯需要使用代碼片段來表示,依賴于用戶編寫的map reduce兩個(gè)函數(shù).這兩個(gè)函數(shù)需要指定處理的方式.
例如MongoDB中MapReduce的功能:

db.observations.mapReduce(
    function map() {
        var year = this.observationTimeStamp.getFullYear();
        var month = this.observationTimeStamp.getMonth() + 1;
        emit(year + "-" + month, this.numAnimals); // 生成KV對 例如:(2020-01,100)
    },
    function reduce(key, values) {
        return Array.sum(values); // 根據(jù)鍵將所有的值求和.
    },
    {
        query:{family: "Sharks"},
        out: "monthlySharkReport"
    }
);

注意:map,reduce兩個(gè)函數(shù)必須為純函數(shù),即不能帶有副作用.

圖狀數(shù)據(jù)模型聲明式查詢語言

屬性圖: Cypher
Cypher是屬性圖的聲明式查詢語言的一種.我們先來看看如何創(chuàng)建數(shù)據(jù).

CREATE
    (NAmerica:Location {name:'North America', type:'contient'}),
    (USA:Location {name:'United States', type:'country'}),
    (Idaho:Location {name:'Idaho', type:'state'}),
    (Lucy:Persion {name:'Lucy', age:33}),
    (Idaho)-[:WITHIN]->(USA)-[:WITHIN]->(NAmerica),
    (Lucy)-[:BORN_IN]->(Idaho) 

使用(NAmerica:Location {name:'North America', type:'contient'})的語句定義圖中的頂點(diǎn).使用(Lucy)-[:BORN_IN]->(Idaho)的語句定義一個(gè)標(biāo)簽為BORN_IN的邊,其中(Lucy)是尾部頂點(diǎn),(Idaho)是頭部定點(diǎn).
使用Cypher進(jìn)行查詢:
示例使用MATCH語句查詢了從USA移民到歐洲的所有人員.

MATCH
    (person)-[:BORN_IN]->()-[:WITHIN*0]->(us:Location {name:'United States'}),
    (person)-[:LIVES_IN]->()-[:WITHIN*0]->(eu:Location {name:'Europe'})
RETURN person.name

解釋:
找到滿足以下兩個(gè)條件的任何頂點(diǎn).

  1. person有一個(gè)到其他頂點(diǎn)的出邊BORN_IN.從該頂點(diǎn)開始沿著這條邊,可以沿著一系列出邊WITHIN,直到最終到達(dá)類型為Location的頂點(diǎn),neme屬性為'United States'.
  2. 同一個(gè)person頂點(diǎn)也有一個(gè)出邊LIVES_IN.從該頂點(diǎn)開始沿著這條邊,可以雁陣一系列出邊WITHIN,直到最終到達(dá)類型為Location的頂點(diǎn),neme屬性為'Europe'.

對于這樣的頂點(diǎn),返回它的name屬性.

三元存儲:SPARQL
SPARQL 是一種采用RDF數(shù)據(jù)模型的三元存儲查詢語言.
其中RDF是資源描述框架,它榮不同的網(wǎng)站以一致的格式發(fā)布數(shù)據(jù),這樣來自不同網(wǎng)站的數(shù)據(jù)自動(dòng)合并成一個(gè)數(shù)據(jù)網(wǎng)絡(luò),形成一種互聯(lián)網(wǎng)級別包含所有數(shù)據(jù)的數(shù)據(jù)庫.
RDF數(shù)據(jù)模型示例
RDF可以采用XML的方式編寫:

<rdf:RDF xmlns="urn:example:"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<Location rdf:nodeID="idaho">
    <name>Idaho</name>
    <type>state</type>
    <within>
        <Location rdf:nodeID="usa">
             <name>United States</name>
             <type>country</type>
             <within>
                 <Location rdf:nodeID="namerica">
                    <name> North America</name>
                    <type>continent</type>
                 </Location>
             </within>
          </Location>
       <within>
</Location>
<Person rdf:nodeID="lucy">
    <name>Lucy</name>
    <bornIn rdf:nodeID="idaho"/>
</Person>
</ref:RDF>

還有更簡單的Turtle/N3這種格式:

@prefix : <urn:exmaple:>.
_:lucy a :Person; :name "Lucy"; :bornIn _:idaho.
_:idaho a :Location; :name "Idaho"; :type "state"; :within _:usa.
_:usa a :Location; :name "United States"; :type "country"; :within _:namerica.
_:namerica a :Location; :name "North America"; :type "continent".

SPARQL查詢語言.
同樣我們使用SPARQL查詢從USA移民到歐洲的人員.

PREFIX : <urn:example:>

SELECT ?personName WHERE {
    ?person :name ?personName.
    ?person :bornIn / :within* / :name "United States".
    ?person :livesIn / :within* / :name "Europe".
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容