一個簡單的指標,你可以嘗試:
創建集合products
,categories
和邊緣收集has_category
。然後生成一些樣本數據:
FOR i IN 1..10000
INSERT {_key: TO_STRING(i), name: CONCAT("Product ", i)} INTO products
FOR i IN 1..10000
INSERT {_key: TO_STRING(i), name: CONCAT("Category ", i)} INTO categories
FOR p IN products
LET random_categories = (
FOR c IN categories
SORT RAND()
LIMIT 5
RETURN c._id
)
LET category_subset = SLICE(random_categories, 0, RAND()*5+1)
UPDATE p WITH {
categories: category_subset,
categoriesEmbedded: DOCUMENT(category_subset)[*].name
} INTO products
FOR cat IN category_subset
INSERT {_from: p._id, _to: cat} INTO has_category
然後比較查詢時間的不同方法。
圖的遍歷(深度1..1):
FOR p IN products
RETURN {
product: p.name,
categories: (FOR v IN OUTBOUND p has_category RETURN v.name)
}
查找在集合類使用文檔():
FOR p IN products
RETURN {
product: p.name,
categories: DOCUMENT(p.categories)[*].name
}
使用直接嵌入類別名稱:
FOR p IN products
RETURN {
product: p.name,
categories: p.categoriesEmbedded
}
圖遍歷是所有3中最慢的,在另一個集合中的查找比遍歷快,但通過最快的查詢是嵌入類別名稱的查詢。
但是,如果僅查詢一個或幾個產品的類別,則響應時間應該在亞毫秒區域,而不管數據模型和查詢方式如何,因此不會造成性能問題。
如果您需要查詢具有可變深度,長路徑,最短路徑等路徑,應該選擇圖方法。對於您的用例,這不是必需的。無論嵌入式方法是否合適,您需要決定:
重複信息是否可以接受,並且可能在數據中存在不一致?(如果要更改類別名稱,則需要在所有產品記錄中對其進行更改,而不僅僅是一個類別文檔,該產品可以通過不可變的ID引用)
是否有大量每類別的附加信息?如果是這樣,所有這些數據需要嵌入到每個產品文檔中 - 基本上交易內存/存儲空間的性能
您是否需要經常檢索所有(不同)類別的列表?您可以使用單獨的類別集合非常便宜地執行此類查詢。採用嵌入式方法時,效率會低得多,因爲您需要查看所有產品並收集類別信息。
底線:您應該選擇最適合您的用例的數據模型和方法。感謝ArangoDB的多模式特性,如果您的用例發生變化或遇到性能問題,您可以輕鬆嘗試其他方法。