摘要:在處理關(guān)聯(lián)關(guān)系,嵌套對(duì)象和父子關(guān)聯(lián)關(guān)系中,我們會(huì)討論幾種可行方案的優(yōu)點(diǎn)和缺點(diǎn)。在關(guān)系數(shù)據(jù)庫(kù)中,處理關(guān)聯(lián)關(guān)系的方式讓你不會(huì)感到意外每個(gè)實(shí)體或者行,在關(guān)系世界中可以通過(guò)一個(gè)主鍵唯一標(biāo)識(shí)。但是關(guān)聯(lián)關(guān)系很重要。
數(shù)據(jù)建模(Modeling Your Data)
ES是一頭不同尋常的野獸,尤其是當(dāng)你來(lái)自SQL的世界時(shí)。它擁有很多優(yōu)勢(shì):性能,可擴(kuò)展性,準(zhǔn)實(shí)時(shí)的搜索,以及對(duì)大數(shù)據(jù)的分析能力。并且,它很容易上手!只需要下載就能夠開(kāi)始使用它了。
但是它也不是魔法。為了更好的利用ES,你需要了解它從而讓它能夠滿足你的需求。
在ES中,處理實(shí)體之間的關(guān)系并不像關(guān)系型存儲(chǔ)那樣明顯。在關(guān)系數(shù)據(jù)庫(kù)中的黃金準(zhǔn)則 - 數(shù)據(jù)規(guī)范化,在ES中并不適用。在處理關(guān)聯(lián)關(guān)系,嵌套對(duì)象和父子關(guān)聯(lián)關(guān)系中,我們會(huì)討論幾種可行方案的優(yōu)點(diǎn)和缺點(diǎn)。
緊接著在為可擴(kuò)展性而設(shè)計(jì)中,我們會(huì)討論ES提供的一些用來(lái)快速靈活實(shí)現(xiàn)擴(kuò)展的特性。對(duì)于擴(kuò)展,并沒(méi)有一個(gè)可以適用于所有場(chǎng)景的解決方案。你需要考慮數(shù)據(jù)是如何在你的系統(tǒng)中流轉(zhuǎn)的,從而恰當(dāng)?shù)貙?duì)你的數(shù)據(jù)進(jìn)行建模。針對(duì)基于時(shí)間的數(shù)據(jù)比如日志事件或者社交數(shù)據(jù)流的方案比相對(duì)靜態(tài)的文檔集合的方案是十分不同的。
最后,我們會(huì)討論一樣在ES中不會(huì)擴(kuò)展的東西。
處理關(guān)聯(lián)關(guān)系(Handling Relationships)
在真實(shí)的世界中,關(guān)聯(lián)關(guān)系很重要:博客文章有評(píng)論,銀行賬戶有交易,客戶有銀行賬戶,訂單有行項(xiàng)目,目錄也擁有文件和子目錄。
在關(guān)系數(shù)據(jù)庫(kù)中,處理關(guān)聯(lián)關(guān)系的方式讓你不會(huì)感到意外:
每個(gè)實(shí)體(或者行,在關(guān)系世界中)可以通過(guò)一個(gè)主鍵唯一標(biāo)識(shí)。
實(shí)體是規(guī)范化了的。對(duì)于一個(gè)唯一的實(shí)體,它的數(shù)據(jù)僅被存儲(chǔ)一次,而與之關(guān)聯(lián)的實(shí)體則僅僅保存它的主鍵。改變一個(gè)實(shí)體的數(shù)據(jù)只能發(fā)生在一個(gè)地方。
在查詢期間,實(shí)體可以被聯(lián)接(Join),它讓跨實(shí)體查詢成為可能。
對(duì)于單個(gè)實(shí)體的修改是原子性,一致性,隔離性和持久性的。(參考ACID事務(wù)獲取更多相關(guān)信息。)
絕大多數(shù)的關(guān)系型數(shù)據(jù)庫(kù)都支持針對(duì)多個(gè)實(shí)體的ACID事務(wù)。
但是關(guān)系型數(shù)據(jù)庫(kù)也有它們的局限,除了在全文搜索領(lǐng)域它們拙劣的表現(xiàn)外。在查詢期間聯(lián)接實(shí)體是昂貴的 - 聯(lián)接的實(shí)體越多,那么查詢的代價(jià)就越大。對(duì)不同硬件上的實(shí)體執(zhí)行聯(lián)接操作的代價(jià)太大以至于它甚至是不切實(shí)際的。這就為在單個(gè)服務(wù)器上能夠存儲(chǔ)的數(shù)據(jù)量設(shè)下了一個(gè)限制。
ES,像多數(shù)NoSQL數(shù)據(jù)庫(kù)那樣,將世界看作是平的。一個(gè)索引就是一系列獨(dú)立文檔的扁平集合。一個(gè)單一的文檔應(yīng)該包括用來(lái)判斷它是否符合一個(gè)搜索請(qǐng)求的所有信息。
雖然在ES中改變一份文檔的數(shù)據(jù)是符合ACIDic的,涉及到多份文檔的事務(wù)就不然了。在ES中,當(dāng)事務(wù)失敗后是沒(méi)有辦法將索引回滾到它之前的狀態(tài)的。
這個(gè)扁平化的世界有它的優(yōu)勢(shì):
索引是迅速且不需要上鎖的。
搜索是迅速且不需要上鎖的。
大規(guī)模的數(shù)據(jù)可以被分布到多個(gè)節(jié)點(diǎn)上,因?yàn)槊糠菸臋n之間是獨(dú)立的。
但是關(guān)聯(lián)關(guān)系很重要。我們需要以某種方式將扁平化的世界和真實(shí)的世界連接起來(lái)。在ES中,有4中常用的技術(shù)來(lái)管理關(guān)聯(lián)數(shù)據(jù):
應(yīng)用端聯(lián)接(Application-side joins)
數(shù)據(jù)非規(guī)范化(Data denormalization)
嵌套對(duì)象(Nested objects)
父子關(guān)聯(lián)關(guān)系(Parent/child relationships)
通常最終的解決方案會(huì)結(jié)合這些方案的幾種。
應(yīng)用端聯(lián)接(Application-side Joins)
我們可以通過(guò)在應(yīng)用中實(shí)現(xiàn)聯(lián)接來(lái)(部分)模擬一個(gè)關(guān)系型數(shù)據(jù)庫(kù)。比如,當(dāng)我們想要索引用戶和他們的博客文章時(shí)。在關(guān)系型的世界中,我們可以這樣做:
PUT /my_index/user/1 (1) { "name": "John Smith", "email": "[email protected]", "dob": "1970/10/24" }
PUT /my_index/blogpost/2 (2) { "title": "Relationships", "body": "It"s complicated...", "user": 1 (3) }
(1)(2) 索引,類型以及每份文檔的ID一起構(gòu)成了主鍵。
(3) 博文通過(guò)保存了用戶的ID來(lái)聯(lián)接到用戶。由于索引和類型是被硬編碼到了應(yīng)用中的,所以這里并不需要。
通過(guò)用戶ID等于1來(lái)找到對(duì)應(yīng)的博文很容易:
GET /my_index/blogpost/_search { "query": { "filtered": { "filter": { "term": { "user": 1 } } } } }
為了找到用戶John的博文,我們可以執(zhí)行兩條查詢:第一條查詢用來(lái)得到所有名為John的用戶的IDs,第二條查詢通過(guò)這些IDs來(lái)得到對(duì)應(yīng)文章:
GET /my_index/user/_search { "query": { "match": { "name": "John" } } }
GET /my_index/blogpost/_search { "query": { "filtered": { "filter": { "terms": { "user": [1] } (1) } } } }
(1) 傳入到terms過(guò)濾器的值是第一條查詢的結(jié)果。
應(yīng)用端聯(lián)接最大的優(yōu)勢(shì)在于數(shù)據(jù)是規(guī)范化了的。改變用戶的名字只需要在一個(gè)地方操作:用戶對(duì)應(yīng)的文檔。劣勢(shì)在于你需要在搜索期間運(yùn)行額外的查詢來(lái)聯(lián)接文檔。
在這個(gè)例子中,只有一位用戶匹配了第一條查詢,但是在實(shí)際應(yīng)用中可能輕易就得到了數(shù)以百萬(wàn)計(jì)的名為John的用戶。將所有的IDs傳入到第二個(gè)查詢中會(huì)讓該查詢非常巨大,它需要執(zhí)行百萬(wàn)計(jì)的term查詢。
這種方法在第一個(gè)實(shí)體的文檔數(shù)量較小并且它們很少改變時(shí)合適(這個(gè)例子中實(shí)體指的是用戶)。這就使得通過(guò)緩存結(jié)果來(lái)避免頻繁查詢成為可能。
反規(guī)范化你的數(shù)據(jù)(Denormalizing Your Data)
讓ES達(dá)到最好的搜索性能的方法是采用更直接的辦法,通過(guò)在索引期間反規(guī)范化你的數(shù)據(jù)。通過(guò)在每份文檔中包含冗余數(shù)據(jù)來(lái)避免聯(lián)接。
如果我們需要通過(guò)作者的名字來(lái)搜索博文,可以在博文對(duì)應(yīng)的文檔中直接包含該作者的名字:
PUT /my_index/user/1 { "name": "John Smith", "email": "[email protected]", "dob": "1970/10/24" }
PUT /my_index/blogpost/2 { "title": "Relationships", "body": "It"s complicated...", "user": { "id": 1, "name": "John Smith" } }
現(xiàn)在,我們可以通過(guò)一條查詢來(lái)得到用戶名為John的博文了:
GET /my_index/blogpost/_search { "query": { "bool": { "must": [ { "match": { "title": "relationships" }}, { "match": { "user.name": "John" }} ] } } }
對(duì)數(shù)據(jù)的反規(guī)范化的優(yōu)勢(shì)在于速度。因?yàn)槊糠菸臋n包含了用于判斷是否匹配查詢的所有數(shù)據(jù),不需要執(zhí)行代價(jià)高昂的聯(lián)接操作。
http://blog.csdn.net/dm_vincent/article/details/47710367
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64523.html
閱讀 1026·2021-11-22 13:52
閱讀 936·2019-08-30 15:44
閱讀 580·2019-08-30 15:43
閱讀 2436·2019-08-30 12:52
閱讀 3484·2019-08-29 16:16
閱讀 645·2019-08-29 13:05
閱讀 2951·2019-08-26 18:36
閱讀 2006·2019-08-26 13:46