1. 程式人生 > 其它 >查詢語句寫了limit 1,為什麼依然很慢?

查詢語句寫了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,進一步提升語句執行速度。

總結

通過這次分析也可以看出,很多時候計算引擎會對語句進行代價估計並調整語句的執行順序。執行計劃是語句如何執行的直觀表達。語句如何執行不能只關注語句寫法,要想寫出符合預期執行順序的查詢語句,還需要關注語句執行計劃。

 

點選關注,第一時間瞭解華為雲新鮮技術~