[英]ArangoDB sharding cluster performance issue
我有一個在單實例設置中運行良好的查詢。 但是,當我嘗試在分片集群上運行它時,性能下降了(執行時間延長了 4 倍)。
查詢計划顯示幾乎所有處理都在 Coordinator 節點上完成,而不是在 DbServer 上。 如何推送要在 DbServer 上執行的查詢?
提供一些背景信息:我收集了大約 120k(將增長到數百萬)的多級 JSON 文檔,其中嵌套了 arrays。 並且查詢需要在到達正確的節點之前取消嵌套這些 arrays。
AQL 查詢:
for doc IN doccollection
for arrayLevel1Elem in doc.report.container.children.container
for arrayLevel2Elem in arrayLevel1Elem.children.container.children.num
for arrayLevel3Elem in arrayLevel2Elem.children.code
filter doc.report.container.concept.simpleCodedValue == 'A'
filter arrayLevel1Elem.concept.codedValue == "B"
filter arrayLevel2Elem.concept.simpleCodedValue == "C"
filter arrayLevel3Elem.concept.simpleCodedValue == 'X'
filter arrayLevel3Elem.value.simpleCodedValue == 'Y'
collect studyUid = doc.report.study.uid, personId = doc.report.person.id, metricName = arrayLevel2Elem.concept.meaning, value = to_number(arrayLevel2Elem.value)
return {studyUid, personId, metricName, value}
查詢計划:
Id NodeType Site Est. Comment
1 SingletonNode DBS 1 * ROOT
2 EnumerateCollectionNode DBS 121027 - FOR doc IN doccollection /* full collection scan, projections: `report`, 2 shard(s) */ FILTER (doc.`report`.`container`.`concept`.`simpleCodedValue` == "A") /* early pruning */
3 CalculationNode DBS 121027 - LET #8 = doc.`report`.`container`.`children`.`container` /* attribute expression */ /* collections used: doc : doccollection */
19 CalculationNode DBS 121027 - LET #24 = doc.`report`.`study`.`uid` /* attribute expression */ /* collections used: doc : doccollection */
20 CalculationNode DBS 121027 - LET #26 = doc.`report`.`person`.`id` /* attribute expression */ /* collections used: doc : doccollection */
29 RemoteNode COOR 121027 - REMOTE
30 GatherNode COOR 121027 - GATHER /* parallel, unsorted */
4 EnumerateListNode COOR 12102700 - FOR arrayLevel1Elem IN #8 /* list iteration */
11 CalculationNode COOR 12102700 - LET #16 = (arrayLevel1Elem.`concept`.`codedValue` == "B") /* simple expression */
12 FilterNode COOR 12102700 - FILTER #16
5 CalculationNode COOR 12102700 - LET #10 = arrayLevel1Elem.`children`.`container`.`children`.`num` /* attribute expression */
6 EnumerateListNode COOR 1210270000 - FOR arrayLevel2Elem IN #10 /* list iteration */
13 CalculationNode COOR 1210270000 - LET #18 = (arrayLevel2Elem.`concept`.`simpleCodedValue` == "C") /* simple expression */
14 FilterNode COOR 1210270000 - FILTER #18
7 CalculationNode COOR 1210270000 - LET #12 = arrayLevel2Elem.`children`.`code` /* attribute expression */
21 CalculationNode COOR 1210270000 - LET #28 = arrayLevel2Elem.`concept`.`meaning` /* attribute expression */
22 CalculationNode COOR 1210270000 - LET #30 = TO_NUMBER(arrayLevel2Elem.`value`) /* simple expression */
8 EnumerateListNode COOR 121027000000 - FOR arrayLevel3Elem IN #12 /* list iteration */
15 CalculationNode COOR 121027000000 - LET #20 = ((arrayLevel3Elem.`concept`.`simpleCodedValue` == "X") && (arrayLevel3Elem.`value`.`simpleCodedValue` == "Y")) /* simple expression */
16 FilterNode COOR 121027000000 - FILTER #20
23 CollectNode COOR 96821600000 - COLLECT studyUid = #24, personId = #26, metricName = #28, value = #30 /* hash */
26 SortNode COOR 96821600000 - SORT studyUid ASC, personId ASC, metricName ASC, value ASC /* sorting strategy: standard */
24 CalculationNode COOR 96821600000 - LET #32 = { "studyUid" : studyUid, "personId" : personId, "metricName" : metricName, "value" : value } /* simple expression */
25 ReturnNode COOR 96821600000 - RETURN #32
非常感謝任何提示。
查詢實際上並沒有在數據庫服務器上執行——協調器處理查詢編譯和執行,只是真正地向數據庫服務器詢問數據。
這意味着用於查詢執行的 memory 負載發生在協調器上(很好。)但是協調器必須通過網絡傳輸(有時是大量的)數據。 這是遷移到集群的最大缺點 - 而不是一個容易解決的問題。
我一開始也走這條路,並找到了優化我的一些查詢的方法,但最后,使用“ 單分片”集群或“ 主動故障轉移”設置更容易實現 go。
提出架構建議很棘手,因為每個用例都可能如此不同,但我遵循一些通用的 AQL 指南:
FOR
和FILTER
語句(參見 #2)。 試試這個版本,看看它是否運行得更快(並嘗試索引report.container.concept.simpleCodedValue
):FOR doc IN doccollection
FILTER doc.report.container.concept.simpleCodedValue == 'A'
FOR arrayLevel1Elem in doc.report.container.children.container
FILTER arrayLevel1Elem.concept.codedValue == 'B'
FOR arrayLevel2Elem in arrayLevel1Elem.children.container.children.num
FILTER arrayLevel2Elem.concept.simpleCodedValue == 'C'
FOR arrayLevel3Elem in arrayLevel2Elem.children.code
FILTER arrayLevel3Elem.concept.simpleCodedValue == 'X'
FILTER arrayLevel3Elem.value.simpleCodedValue == 'Y'
COLLECT
studyUid = doc.report.study.uid,
personId = doc.report.person.id,
metricName = arrayLevel2Elem.concept.meaning,
value = to_number(arrayLevel2Elem.value)
RETURN { studyUid, personId, metricName, value }
FOR doc IN doccollection
模式將從數據庫服務器中為doccollection
中的每個項目調用整個文檔。 最佳做法是限制您要檢索的文檔數量(最好使用索引支持的搜索)和/或只返回幾個屬性。 不要害怕使用LET
- 協調器上的內存可以比數據庫上的內存更快。 此示例同時進行 - 過濾並返回一組較小的數據:LET filteredDocs = (
FOR doc IN doccollection
FILTER doc.report.container.concept.simpleCodedValue == 'A'
RETURN {
study_id: doc.report.study.uid,
person_id: doc.report.person.id,
arrayLevel1: doc.report.container.children.container
}
)
FOR doc IN filteredDocs
FOR arrayLevel1Elem in doc.arrayLevel1
FILTER arrayLevel1Elem.concept.codedValue == 'B'
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.