neo4j cypher_优化Neo4j Cypher查询
neo4j cypher
上周,我花了很多時(shí)間來嘗試優(yōu)化大約20個(gè)使用實(shí)時(shí)系統(tǒng)數(shù)據(jù)執(zhí)行的災(zāi)難性的Cypher查詢(36866ms至155575ms)。 經(jīng)過一番嘗試和錯(cuò)誤,以及來自Michael的大量投入,我能夠大致確定對(duì)查詢進(jìn)行哪些操作才能使它們性能更好-最后,性能最差的查詢降至521ms。冷圖和1GB堆空間(并且該查詢具有可選路徑-不確定如何改進(jìn)),其余都在50ms以下-與原始數(shù)字相比有很大改進(jìn)。
希望這可能對(duì)其他人有所幫助,這就是我所做的事情(大多數(shù)是猜測工作,并且在很大程度上是不科學(xué)的)-也許Michael可以幫助解釋內(nèi)部原理,并根據(jù)某些假設(shè)對(duì)我進(jìn)行糾正。 我要做的第一件事是確保每個(gè)密碼查詢都使用參數(shù)-如Neo4j文檔中所述 ,這有助于緩存執(zhí)行計(jì)劃。
其次,我在Neo4j郵件列表中碰到了一個(gè)帖子,邁克爾在其中提到不重新實(shí)例化ExecutionEngine,以便上述參數(shù)化查詢實(shí)際上可以緩存。 對(duì)于許多人來說,這似乎很明顯,但這是一個(gè)容易被忽視的事實(shí),因?yàn)槲矣幸粋€(gè)名為QueryExecutor的類,該類包含一個(gè)執(zhí)行帶有參數(shù)映射的查詢的方法,并且該方法為每個(gè)查詢創(chuàng)建了一個(gè)新的ExecutionEngine。 一旦編寫并多次使用了此方法,就很容易忘記。 但是,這是影響整體性能的一個(gè)非常重要的因素(文檔中的提及將非常有幫助),它解釋了為什么即使在參數(shù)化的情況下,我的查詢通常也需要花費(fèi)相同的時(shí)間來執(zhí)行。 將其更改為使用緩存的ExecutionEngine,可以看到我的查詢時(shí)間工作表的下半部分下降了……在緩存之后0到1毫秒-取得了出色的進(jìn)展。
現(xiàn)在,要開始每個(gè)查詢,從最壞的情況開始。 我決定在僅分配1GB堆空間的本地計(jì)算機(jī)上和冷圖上進(jìn)行優(yōu)化。 因此,我忽略了緩存后查詢執(zhí)行的改進(jìn)-我認(rèn)為這是確保進(jìn)度的一種更好的方法-如果第一個(gè)查詢命中沒有改善,那么您確實(shí)沒有對(duì)其進(jìn)行優(yōu)化。 這樣,如果它在有限的硬件上確實(shí)可以很好地工作,我對(duì)它在生產(chǎn)中可以更好地工作充滿信心。
除了在代碼中安排查詢時(shí)間之外,我還使用webadmin控制臺(tái)進(jìn)行了優(yōu)化。 該查詢糟糕的指標(biāo)是它不會(huì)返回并且控制臺(tái)將掛起。 優(yōu)化以使其不會(huì)掛起本身就是一個(gè)重大改進(jìn)。 高度不科學(xué),但我建議這樣做。
我的第一個(gè)查詢平均大約為76558ms(該時(shí)間是通過在引擎execute方法周圍添加開始時(shí)間和結(jié)束時(shí)間而獲得的)。 第一次優(yōu)化后,它減少到466ms。 這是原始查詢: https : //gist.github.com/4436272
這是經(jīng)過優(yōu)化的一個(gè): https ://gist.github.com/4436281不需要執(zhí)行此巨大匹配只是為了基于a的alertDate屬性過濾出結(jié)果,因此我減少了匹配以返回最小的集合首先可以過濾的數(shù)據(jù),即 通往的道路
如果要在第一次匹配之前執(zhí)行錯(cuò)誤查詢,則會(huì)看到返回2萬行之類的信息。 過濾后,它們只有450個(gè)奇數(shù)行。 可以想象,第二個(gè)查詢Swift減少了可能要使用的結(jié)果數(shù)量。
第二個(gè)變化是我那天從邁克爾那里學(xué)到的東西,當(dāng)時(shí)我問做大型比賽還是繼續(xù)修剪子查詢是否有意義。 他的回答是:“ 問題是,您是在使用match來通過描述模式來實(shí)際擴(kuò)展結(jié)果集,還是只是要確定是否存在某些關(guān)系(也稱為“過濾”)。 如果是后者,則可能要在where子句中使用path-expression語法。
WHERE a-[:FOO]->b or WHERE NOT(a-[:FOO]->b)'這花了一點(diǎn)時(shí)間來適應(yīng),因?yàn)槲揖帉慚ATCH子句的方式恰恰是我腦子里的想法,但是現(xiàn)在我可以區(qū)分出所需結(jié)果的匹配項(xiàng)與過濾器的匹配項(xiàng)了。 在上面的查詢中,我的結(jié)果中需要(ir),因此無需在匹配中包含(a)-[:alert_for_inspection]->(i); 我可以在WHERE中使用它來確保a確實(shí)與i有關(guān)。
這是另一個(gè)示例: https : //gist.github.com/4436293
立刻,您會(huì)看到我們按日期過濾了厘米關(guān)系-如果它們不在日期范圍內(nèi),則無需我們先進(jìn)行匹配。 因此,查詢的這一部分可以重寫為:
start c=node:companies(id={id}) match c <-[parent_company*0..]-(n)with n match n-[:defines_business_process]->(bp)-[:has_cycle]->(cm) where cm.measureDate>={measureStartDate} and cm.measureDate<={measureEndDate}在那之后,下一個(gè)過濾器是相同的:
with cm match (cm)-[:cycle_metric] ->m-[:metric_activity] ->ma-[:metric_unit] -> (u)-[:alert_for_unit]-(a) where a.alertDate=cm.measureDate and a.fromEntityType={type}這進(jìn)一步修剪了我們的結(jié)果集。 最后,將連接添加到r(以得到我們的結(jié)果),確保沒有導(dǎo)致r產(chǎn)生但必不可少的路徑進(jìn)入WHERE子句:
with a,ma match (r) < - [:for_inspection_result]-a-[:alert_for_inspection]- > i where (i) < -[:metric_inspection]-(ma) return a.id as alertId, r.value as resultValue這是完整的查詢: https ://gist.github.com/4436328原始時(shí)間-33360毫秒,優(yōu)化后-246毫秒。
至少對(duì)我來說,我的大多數(shù)查詢都屬于這種模式,所以到第二天,我就能夠非常快速地重構(gòu)它們。 有趣的是,此后,我仍然感到響應(yīng)緩慢,但是在日志中打印的查詢時(shí)間很小。 消除之后,我發(fā)現(xiàn)我的代碼在執(zhí)行查詢之后(由executionEngine.execute)實(shí)際上停留了很長時(shí)間,但是在結(jié)果集的第一次迭代中。我假設(shè)結(jié)果不一定在execute()方法期間收集,但是在結(jié)果集的迭代中比較懶惰-我不了解Cypher內(nèi)部結(jié)構(gòu),因此我可能完全錯(cuò)了。 但是定時(shí)迭代本身可以指出更糟糕的查詢。
其他點(diǎn)點(diǎn)滴滴-ORDER BY增加了很多時(shí)間。 如果沒有它,那是您應(yīng)該放棄的第一件事。 DISTINCT還增加了時(shí)間,但是在我的許多情況下,很難刪除它。
如果要檢查是否缺少可選路徑,通常在哪里進(jìn)行MATCH(u)-[r?:has_a]-(a)WHERE NOT(r為null),而是改寫為MATCH(u)-[ other_stuff]-.. WHERE NOT(u-[:has_a] -a)的效果要好得多。 但是,在我有諸如MATCH X- [o?:optional] -Y WHERE(存在o,將Y匹配到A和B)或OR(不存在o,將X匹配到c和d)的可選路徑的地方,我無法簡化與沒有可選路徑的其他查詢相比,這些查詢?nèi)孕枰恍r(shí)間。
最終-發(fā)現(xiàn)問題的時(shí)間太晚了,因?yàn)闇y試數(shù)據(jù)永遠(yuǎn)不會(huì)與實(shí)時(shí)數(shù)據(jù)非常接近。 圖的結(jié)構(gòu)起著很大的作用-一些節(jié)點(diǎn)是緊密連接的,而其他節(jié)點(diǎn)則不是那么重要-并且涉及那些緊密連接的節(jié)點(diǎn)的查詢是對(duì)我們最大的傷害。 盡可能嘗試使用生產(chǎn)質(zhì)量數(shù)據(jù)進(jìn)行性能測試,或者嘗試創(chuàng)建與之類似的測試數(shù)據(jù)。
因此,總結(jié)一下:
參考: Thought Bytes博客上來自我們JCG合作伙伴 Aldrin和Luanne Misquitta的優(yōu)化Neo4j Cypher查詢 。
翻譯自: https://www.javacodegeeks.com/2013/01/optimizing-neo4j-cypher-queries.html
neo4j cypher
總結(jié)
以上是生活随笔為你收集整理的neo4j cypher_优化Neo4j Cypher查询的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网信部门依法查处腾讯 QQ 危害未成年人
- 下一篇: http缓存管理器_小心缓存管理器