ES中多表關聯(lián)如何解決

整個文檔纹磺,摘錄來自"銘毅天下"的博客蕉斜。原始的地址如下:

Elasticsearh多表關聯(lián)設計

引入問題

多表關聯(lián)通常是指:1對多洒试,或者多對多關系在ES中的呈現(xiàn)硼莽。

比如:博客和評論的關系庶溶,用戶和愛好的關系,主表和子表的關系懂鸵。

es_mulit_table_join1.png

基礎認知

關系型數(shù)據(jù)庫

關系型數(shù)據(jù)庫是專門為關系設計的偏螺,有如下特點:

  • 可以通過主鍵唯一地標識每個實體(如Mysql中的行)。

  • 實體規(guī)范化匆光。唯一實體的數(shù)據(jù)只存儲一次套像,而相關實體只存儲它的主鍵。只能在一個具體位置修改這個實體的數(shù)據(jù)终息。

  • 實體可以進行關聯(lián)查詢夺巩,可以跨實體搜索。

  • 支持AICD特性周崭,即:單個實體的變化是原子的柳譬、一致的、隔離的和持久的续镇。

  • 大多數(shù)關系型數(shù)據(jù)庫支持跨多個實體的ACID事務美澳。

關系型數(shù)據(jù)庫的缺陷:

  • 第一:全文檢索有限的支持能力。這點摸航,postgresql已部分支持制跟,但相對有限。

  • 第二:多表關聯(lián)查詢的耗時很長酱虎,甚至不可用凫岖。之前系統(tǒng)開發(fā)中使用過Mysql8個表做關聯(lián)查詢,一次查詢等待十分鐘以上逢净,甚至不可用。

Elasticsearch

ES和大多數(shù)NoSQL數(shù)據(jù)庫類似,是扁平化的爹土。索引是獨立文檔的集合體甥雕。文檔是否匹配搜索請求取決于它是否包含所有的所需信息和關聯(lián)程度。

ES中單個文檔的數(shù)據(jù)變更是滿足ACID的胀茵,但是如果涉及多個文檔時的刪除社露,修改時,則不支持事務琼娘。當一個事務中的部分文檔更新失敗的時候峭弟,是無法將所有涉及到的事務內(nèi)的文檔更新操作都回滾到之前狀態(tài)的。

扁平化有如下的優(yōu)勢:

  • 索引過程是快速和無鎖的脱拼。

  • 搜索過程是快速和無鎖的瞒瘸。

  • 因為每個文檔相互都是獨立的,大規(guī)模數(shù)據(jù)可以在多個節(jié)點上進行分布熄浓。

Mysql VS Elasticsearch

mysql擅長關系管理情臭,而ES擅長的是檢索。

Medcl也曾強調(diào):"如果可能赌蔑,盡量在設計時使用扁平的文檔模型俯在。"ES的關聯(lián)存儲、檢索娃惯、聚合操作勢必會有非常大的性能開銷跷乐。

es_mulit_table_join2.png

ES場景中如何解決這種關聯(lián)關系

關聯(lián)關系仍然非常重要。某些時候趾浅,我們需要縮小扁平化和現(xiàn)實世界關系模型的差異愕提。有如下的四種常用的方法,用來在ES中進行關聯(lián)數(shù)據(jù)的管理潮孽。

應用端關聯(lián)

這是普遍使用的技術揪荣,即在應用接口層面來處理關聯(lián)關系。

針對上面的問題往史,來如下實踐:

1\. 存儲層面:獨立兩個索引存儲
2\. 實際業(yè)務層面分兩次請求:
第一次查詢返回:Top5中文姓名和成績仗颈;
根據(jù)第一次查詢的結果中,取出中文姓名椎例。
到第二個表中進行查詢挨决,返回對應的Top5中文姓名和英文姓名。
最后將第一次查詢結果和第二次查詢結果組合后订歪,返回給用戶脖祈。
即:實際業(yè)務層面是進行兩次查詢,統(tǒng)一返回給用戶刷晋。用戶是無感知的盖高。

適用場景:數(shù)據(jù)量少的業(yè)務場景慎陵。

優(yōu)點:數(shù)據(jù)量少時,用戶體驗好喻奥。

缺點:數(shù)據(jù)量大席纽,兩次查詢耗時肯定會比較長,影響用戶體驗撞蚕。

引申場景:關系型數(shù)據(jù)庫和ES結合润梯,各取所長。將關系型數(shù)據(jù)庫全量同步到ES存儲甥厦,不做冗余處理纺铭。

如前所述:ES擅長的是檢索,而MySQL才擅長關系管理刀疙。所以可以考慮二者結合舶赔,使用ES多索引建立相同的別名,針對別名檢索到對應ID后再回MySQL查詢庙洼,業(yè)務層面通過關聯(lián)ID join 出需要的數(shù)據(jù)顿痪。

寬表冗余存儲

對每個文檔保持一定數(shù)量的冗余數(shù)據(jù)可以在需要訪問時避免進行關聯(lián)。

這點通過logstash同步關聯(lián)數(shù)據(jù)到ES時油够,通常會建議:先通過視圖對MySQL數(shù)據(jù)做好多表關聯(lián)蚁袭,然后同步視圖數(shù)據(jù)到ES。此處的視圖就是寬表石咬。

針對最開始提出的問題:姓名揩悄、英文名、成績兩張表合為一張表存儲鬼悠。

適用場景:一對多或者多對多關聯(lián)删性。

優(yōu)點:速度快。因為每個文檔都包含了所需的所有信息焕窝,當這些信息需要在查詢進行匹配時蹬挺,并不需要進行昂貴的關聯(lián)操作。

缺點:索引更新或刪除數(shù)據(jù)它掂,應用程序不得不處理寬表的冗余數(shù)據(jù)巴帮;由于冗余數(shù)據(jù),導致某些搜索和聚合操作可能無法按照預期工作虐秋。

嵌套文檔nested存儲

Nested類型是ES mapping定義的集合類型之一榕茧,它解決了原有object類型扁平化的字段屬性,導致查詢錯誤的問題客给,是支持獨立檢索的類型用押。

舉例:有一個文檔描述了一個帖子和一個包含帖子上所有評論的內(nèi)部對象評論“薪#可以借助于Nested實現(xiàn)蜻拨。

實踐注意1:當使用嵌套文檔時池充,使用通用的查詢方式是無法訪問到的,必須使用合適的查詢方式(nested query缎讼、nested filter纵菌、nested facet等),很多場景下休涤,使用嵌套文檔的復雜度在于索引階段對關聯(lián)關系的組織拼裝。

實踐注意2:

index.mapping.nested_fields.limit 缺省值為50
即:一個索引中最大允許擁有50個nested類型的數(shù)據(jù)笛辟。
index.mapping.mested_object.limit 缺省值是10000功氨。
即:1個文檔中所有nested類型json對象數(shù)據(jù)的總量是10000。

適用場景:對少量手幢,子文檔偶爾更新捷凄、查詢頻繁的場景。

如果需要索引對象數(shù)組并保持數(shù)組中每個對象的獨立性围来,則應使用嵌套Nested數(shù)據(jù)類型而不是對象Object數(shù)據(jù)類型跺涤。

優(yōu)點:nested文檔可以將父子關系的兩部分數(shù)據(jù)(舉例:博客+評論)關聯(lián)起來,可以基于nested類型做任何的查詢监透。

缺點:查詢相對慢桶错,更新子文檔需要更新整篇文檔。

父子文檔存儲

注意:6.X之前的版本的父子文檔存儲在相同索引的不同type中胀蛮。而6.X之上的版本院刁,單索引下已不存在多type的概念。父子文檔Join的都是基于相同索引相同type實現(xiàn)的粪狼。

Join類型是ES mapping定義的類型之一退腥,用于在同一索引的文檔中創(chuàng)建父/子關系。關系部分定義文檔中的一組可能關系再榄,每個關系是父名稱和子名稱狡刘。

適用場景:子文檔數(shù)據(jù)量要明顯多于父文檔的數(shù)據(jù)量,存在1對多的關系困鸥;子文檔更新頻繁的場景嗅蔬。

舉例:1個產(chǎn)品和供應商之間是1對N的關聯(lián)關系。

當使用父子文檔時窝革,使用has_child或has_parent做父子關聯(lián)查詢购城。

優(yōu)點:父子文檔可以獨立更新。

缺點:維護Join關系需要占據(jù)部分內(nèi)存虐译,查詢較Nested更耗資源瘪板。

小結

Nested Object和父子關系的這兩種的區(qū)別如下:

對比 Nested Object Parent/Child
優(yōu)點 文檔存儲在一起,因此讀取性能高 父子文檔可以獨立更新漆诽,互不影響
缺點 更新父或子文檔時需要更新整個文檔 為了維護Join的關系侮攀,需要占用部分內(nèi)存讀取性能較差
場景 子文檔偶爾更新锣枝,查詢頻繁 子文檔更新頻繁

注意1:在ES開發(fā)實戰(zhàn)中對于多表關聯(lián)的設計要突破關系型數(shù)據(jù)庫設計的思維定式。

注意2:不建議在ES做Join操作兰英,父子能實現(xiàn)部分功能撇叁,但是它的開銷比較大,如果有可能畦贸,盡量在設計時使用扁平的文檔模型陨闹。

注意3:盡量將業(yè)務轉化為沒有關聯(lián)關系的文檔形式,在文檔建模處多下功夫薄坏,以提升檢索效率趋厉。

注意4:Nested&Join父子類型,在選項時必須考慮性能問題胶坠。nested類型檢索使得檢索效率慢幾倍君账,父子Join類型檢索會使得檢索效率慢幾百倍。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沈善,一起剝皮案震驚了整個濱河市乡数,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌闻牡,老刑警劉巖净赴,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異澈侠,居然都是意外死亡劫侧,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門哨啃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烧栋,“玉大人,你說我怎么就攤上這事拳球∩笮眨” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵祝峻,是天一觀的道長魔吐。 經(jīng)常有香客問我,道長莱找,這世上最難降的妖魔是什么酬姆? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮奥溺,結果婚禮上辞色,老公的妹妹穿的比我還像新娘。我一直安慰自己浮定,他們只是感情好相满,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布层亿。 她就那樣靜靜地躺著,像睡著了一般立美。 火紅的嫁衣襯著肌膚如雪匿又。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天建蹄,我揣著相機與錄音碌更,去河邊找鬼。 笑死洞慎,一個胖子當著我的面吹牛针贬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拢蛋,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蔫巩!你這毒婦竟也來了谆棱?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤圆仔,失蹤者是張志新(化名)和其女友劉穎垃瞧,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坪郭,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡个从,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了歪沃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗦锐。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沪曙,靈堂內(nèi)的尸體忽然破棺而出奕污,到底是詐尸還是另有隱情,我是刑警寧澤液走,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布碳默,位于F島的核電站,受9級特大地震影響缘眶,放射性物質(zhì)發(fā)生泄漏嘱根。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一巷懈、第九天 我趴在偏房一處隱蔽的房頂上張望该抒。 院中可真熱鬧,春花似錦砸喻、人聲如沸柔逼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽愉适。三九已至犯助,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間维咸,已是汗流浹背剂买。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留癌蓖,地道東北人瞬哼。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像租副,于是被迫代替她去往敵國和親坐慰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355