查詢語句寫了limit 1,為什麼依然很慢?
摘要: 很多時候計算引擎會對語句進行代價估計並調整語句的執行順序。執行計劃是語句如何執行的直觀表達。語句如何執行不能只關注語句寫法,要想寫出符合預期執行順序的查詢語句,還需要關注語句執行計劃。
本文分享自華為雲社群《查詢語句寫了limit 1,為什麼依然很慢? 記一次圖引擎GES cypher慢查詢的定位分析》,作者: 蜉蝣與海。
問題背景
最近使用華為圖引擎GES, 有一條cypher語句攜帶字尾limit 1,理論上應該很快返回結果,可是跑了很久依舊沒有返回,簡化後的語句如下:
match(v)-[r1:dependency *1..1]->(node) where node.product_name = "product" match path = (m)-[r:dependency*0..10]-> (v:Material) return path, m,node skip 0 limit 10
調整limit 10至limit 1,結果依舊很慢。
在華為雲圖引擎GES官網文件上,發現了對查詢語句進行終止的介面:
首先使用listQueries查詢出當前cypher語句的queryId,然後把queryId輸入killQuery中終止慢查詢。
問題分析:為什麼limit配置為1,依舊長時間無結果?
在華為雲圖引擎控制檯,使用explain列印cypher查詢計劃,分析慢查詢生成原因,簡化後的查詢計劃如圖:
可以看到,查詢語句的執行和預期有差異。查詢語句優先執行了一個Label掃描運算元(NodeByLabelScan),對掃描到的每個點按入邊方向進行了[r*0..10]這樣的10跳操作,而後再從出邊方向做了一跳並過濾,這就導致了最壞情況下,需要全圖Label為Material的點都跳完10跳,才能拿到一條結果。如上圖表格所示,在遍歷到第一個滿足條件的(vi)之前,已經對(v0)到(vi)這些點都做了10跳。即使語句末尾寫了limit 1,因為始終遍歷不到合適的資料,導致了後臺的計算引擎一直在做計算。
估計計算引擎在讀取這條語句時,同時看到了v:Material和node.product='xxx'兩個過濾條件,而代價估計模型認為v:Material可以獲得更低的代價,所以才選擇優先執行NodeByLabelScan。
使用語句優化策略對語句進行優化
既然分析清楚了原因,那麼只要通過改寫cypher語句,讓GES的cypher不優先通過v:Material做計劃即可。這裡用到下列兩類策略:
with別名策略:使用with為變數安排別名,強制規定語句不同子句的執行順序
label過濾改寫策略:將label過濾條件放在where語句中,並使用labels函式,防止生成NodeByLabelScan的計劃
使用with別名策略後,語句如下:
match(v0)-[r1:dependency *1..1]->(node) where node.product_name = "product" with v0 as v,node match path = (m)-[r:dependency*0..10]-> (v:Material) return path, m,node skip 0 limit 10
使用label過濾改寫策略,語句如下:
match(v)-[r1:dependency *1..1]->(node) where node.product_name = "product" match path = (m)-[r:dependency*0..10]-> (v) where labels(v)='Material' return path, m,node skip 0 limit 10
兩種策略混合使用,語句如下:
match(v0)-[r1:dependency *1..1]->(node) where node.product_name = "product" with v0 as v,node match path = (m)-[r:dependency*0..10]-> (v) where labels(v)= " Material" return path, m,node skip 0 limit 10
使用explain將三種查詢計劃分別列印,如圖:
可以看到with別名更有效,生成的計劃更符合期望。
使用with別名策略改寫cypher語句後,語句執行時間從130秒降到3秒。語句中依舊存在AllNodesScan運算元,而華為圖引擎GES是支援索引能力的,後續會考慮加入合適的索引,把AllNodesScan和Filter優化為NodeIndexSeek,進一步提升語句執行速度。
總結
通過這次分析也可以看出,很多時候計算引擎會對語句進行代價估計並調整語句的執行順序。執行計劃是語句如何執行的直觀表達。語句如何執行不能只關注語句寫法,要想寫出符合預期執行順序的查詢語句,還需要關注語句執行計劃。