2017-09-01 62 views
1

版本信息:「查詢LIMIT 1」需要永遠,而「......其中x LIMIT 1個查詢」是瞬間

{ 
    "edition" : "enterprise", 
    "version" : "3.2.2" 
} 

我有標籤U和標籤D.每天幾百萬的實例一的Neo4j數據庫U通過關係WITH_D連接到一個D。幾個我們可能共享相同的D.我的目標是獲得一個D和連接到它的所有我們的列表。

爲什麼這首先查詢掛起無限期量...

match (d:D)<-[:WITH_D]-(u:U) 
return d, collect(u) limit 1 

而這一次在幾毫秒立即返回?

match (d:D) with d limit 1 
match (d)<-[:WITH_D]-(u:U) 
return d, collect(u) 

用於第一查詢計劃涉及節點逐標籤掃描產生幾百萬個節點,然後「展開全部」產生幾百萬個節點,而第二個是一個節點逐標籤與過濾器掃描下至一個節點,然後「全部展開」。

似乎有限制的方式處理的問題,即在某些情況下,它是不夠懶惰。 這會導致大量難處理的子查詢以避免非終止查詢。隨着數據庫接近10億個節點,我多次遇到這個問題。任何線索?

感謝

回答

1

我認爲,主要的一點是這裏的地方是你在查詢中使用LIMIT 1

在第一個查詢你是MATCH首先:D:U標籤之間的荷蘭國際集團ALL可能的模式。在查詢結束時,您將結果限制爲1.也就是說:您匹配所有模式,並在整個結果中使用「作爲過濾器」作爲過濾器「LIMIT」。

在第二個查詢中,您是MATCH ing :D節點限制爲一個。之後,您將所有:U連接到此單個節點。那就是:第一個MATCH正在確定當找到第一個出現:D節點時。因此LIMIT正在使用讀取時間而不僅僅是在返回整個結果之前。

+0

你說得對,這就是查詢的文本所說 - 但我相信這兩個查詢應該有相同的結果和相同的性能。 考慮我們想要得到1個節點的情況。我們會寫: match(n)return n limit 1 很明顯,我們並不期望它首先得到* all *節點,然後只是修剪到第一個。執行引擎在這種情況下是懶惰的,因爲它應該是,然後只是一個節點退出。我在猜測「收集」聚合器是什麼在這裏跳過查詢計劃者。 – user19650

+0

@ user19650我相信這裏的問題是你理解'LIMIT'語句的方式。 LIMIT不是整個查詢的相對部分,而是整個查詢的一部分。您可以使用'LIMIT'來限制'RETURN'或'WITH'輸出中的行數。例如,您可以執行:match(d:D)with d limit 1 match(d)< - [:WITH_D] - (u:U) return d,collect(u) –

+0

@ user19650在您的第一個查詢中, LIMIT與WITH相關。在第二個查詢中,LIMIT相對於整個RETURN。 –