99久久国产露脸精品麻豆,欧美日韩精品小说,亚洲免费在线美女视频,国产三级中文字幕,91极品国产情侣高潮对白,国产亚洲一区二区三区不卡片,欧美jizz精品欧美性,久久国产精品久久国产片

Elasticsearch之join關聯查詢

袁志蒙 1644次瀏覽

摘要:在Elasticsearch這樣的分布式系統中執行類似SQL的join連接是代價是非常大的。然而,Elasticsearch卻給我們提供了基于水平擴展的兩種連接形式。一、join總述1、關系類比在關系...

在Elasticsearch這樣的分布式系統中執行類似SQL的join連接是代價是非常大的。然而,Elasticsearch卻給我們提供了基于水平擴展的兩種連接形式。

一、join總述

1、關系類比

在關系型數據庫中,以MySQL為例,我們經常用到join關鍵字對有關系的兩張或者多張表進行關聯查詢。但是當數據量達到一定量級時,查詢性能就是經常困擾的問題。

由于es可以做到數億量級的秒查(具體由分片數量決定),這時候把數據同步到es是我們可以使用解決方案之一。

那么不禁有疑問問了,由于業務場景的決定,之前必須關聯查詢的兩張表還能做到進行關聯嗎?

答案是可以的,es也提供了類似于關系型數據庫的關聯查詢,但是它又與關系型數據的關聯查詢有明顯的區別與限制。


2、使用限制

由于es屬于分布式文檔型數據庫,數據自然是存在于多個分片之上的。Join字段自然不能像關系型數據庫中的join使用。在es中為了保證良好的查詢性能,最佳的實踐是將數據模型設置為非規范化文檔,通過字段冗余構造寬表,即存儲在一個索引中。


(1)父子文檔(數據)必須存儲在同一index中

(2)父子文檔(數據)必須存儲在同一個分片中

(3)一個index中只能包含一個join字段,但是可以有多個關系

(4)同一個index中,一個父關系可以對應多個子關系,一個子關系只對應一個父關系


3、性能問題

當然執行了join查詢固然性能會受到一定程度的影響。對于帶 has_child / has_parent 而言,其查詢性能會隨著指向唯一父文檔的匹配子文檔的數量增加而降低。開篇第一句摘自es官網描述,從ES官方的描述來看join關聯查詢對性能的損耗是極大的

不過,在筆者使用的過程中,在6個分片的前提下,且子表數據量在千萬量級的情況下,關聯查詢的耗時還是在秒內的,許多場景還是可以接受的。

建議我們在使用前,根據分片的多少和預估未來數據量的大小提前做好性能測試,防止以后數量達到一定程度時,性能有明顯下降,那個時候再改存儲方案得不償失。

二、Mapping

1、舉例說明

這里以優惠券活動與優惠券明細為例,在一個優惠券活動中可以發放幾千萬的優惠券,所以券活動與券明細是一對多的關系。

券活動表字段:

字段 說明

activity_id 活動ID

activity_name 活動名稱


券明細表字段:

字段 說明

coupon_id 券ID

coupon_amount 券面額

activity_id 外鍵-活動ID


2、mapping釋義

join類型的字段主要用來在同一個索引中構建父子關聯關系。通過relations定義一組父子關系,每個關系都包含一個父級關系名稱和一個或多個子級關系名稱activity_coupon_field是一個關聯字段,內部定義了一組join關系,該字段為自命名,type指定關聯關系是join,固定寫法,relations定義父子關系,activity父類型名稱,coupon子類型名稱,名稱均為自命名。

{
	"mappings": {
		"properties": {
			"activity_coupon_field": {
				"type": "join",
				"relations": {
					"activity": "coupon"
				}
			},
			"activity_id": {
				"type": "keyword"
			},
			"activity_name": {
				"type": "keyword"
			},
			"coupon_id": {
				"type": "long"
			},
			"coupon_amount": {
				"type": "long"
			}
		}
	}
}

三、插入數據

1、插入父文檔

在put父文檔數據的時候,我們通常按照某種規則指定文檔ID,方便子文檔數據變更時易于得到父文檔ID。比如這里我們用activity_id的值:activity_100來作為父id

PUT /coupon/_doc/activity_100
 
{
	"activity_id": 100,
	"activity_name": "年貨節5元促銷優惠券",
	"activity_coupon_field": {
		"name": "activity"
	}
}

2、插入子文檔

上邊已經指定了父文檔ID,而子表中已經包含有activity_id,所以很容易得到父文檔ID。

put子文檔數據時候,必須指定父文檔ID,就是父文檔中的_id,這樣父子數據才建立了關聯關系。與此同時還要指定routing字段為父文檔ID,這樣保證了父子數據在同一分片上。

PUT /coupon/_doc/coupon_711235?routing=activity_id_100
 
{
	"coupon_id": 711235,
	"coupon_amount": "5",
	"activity_id": 100,
	"activity_coupon_field": {
		"name": "coupon",
		"parent": "activity_id_100" //父ID
	}
}

四、關聯查詢

1、has_parent查詢(父查子)

根據父文檔條件字段查詢符合條件的子文檔數據

例如:查詢包含“年貨節”活動字樣,且已經被領取過的券

{
	"query": {
		"bool": {
			"must": [{
				"parent_type": "activity",
				"has_parent": {
					"query": {
						"bool": {
							"must": [{
								"term": {
									"status": {
										"value": 1
									}
								}
							}, {
								"wildcard": {
									"activity_name": {
										"wildcard": "*年貨節*"
									}
								}
							}]
						}
					}
				}
			}]
		}
	}
}

2、has_child查詢(子查父)

根據子文檔條件字段符合條件的父文檔數據

例如:查詢coupon_id=711235在那個存在于哪個券活動中

{
	"query": {
		"bool": {
			"must": [{
				"has_child": {
					"type": "coupon",
					"query": {
						"bool": {
							"must": [{
								"term": {
									"coupon_id": {
										"value": 711235
									}
								}
							}]
						}
					}
				}
			}]
		}
	}
}


隨機內容

表情

共0條評論
  • 這篇文章還沒有收到評論,趕緊來搶沙發吧~