如何把php做的网站做成app,网络营销做得好的酒店,网站域名到期,微建站官网上周#xff0c;我花了很多时间尝试使用实时系统中的数据来优化大约20个执行失败的Cypher查询#xff08;36866ms至155575ms#xff09;。 经过一番尝试和错误#xff0c;以及来自Michael的大量投入#xff0c;我能够大致确定对查询进行哪些操作才能使它们性能更好-最后我花了很多时间尝试使用实时系统中的数据来优化大约20个执行失败的Cypher查询36866ms至155575ms。 经过一番尝试和错误以及来自Michael的大量投入我能够大致确定对查询进行哪些操作才能使它们性能更好-最后性能最差的查询降至521ms冷图和1GB堆空间并且该查询具有可选路径-不确定如何改进其余都在50ms以下-与原始数字相比有很大改进。 希望这可能对其他人有所帮助这就是我所做的事情大多数是猜测工作并且在很大程度上不科学-也许Michael可以帮助解释内部原理并根据某些假设对我进行纠正。 我要做的第一件事是确保每个密码查询都使用参数-如Neo4j文档中所述 这有助于缓存执行计划。   其次我遇到了Neo4j邮件列表中的一则帖子其中Michael提到不要重新实例化ExecutionEngine以便上述参数化查询实际上可以缓存。 对于许多人来说这似乎很明显但这是一个容易被忽视的事实因为我有一个名为QueryExecutor的类该类包含一个执行带有参数映射的查询的方法并且该方法为每个查询创建了一个新的ExecutionEngine。 一旦编写并多次使用了此方法就很容易忘记。 但是这是影响整体性能的一个非常重要的因素文档中的提及将非常有帮助它解释了为什么即使在参数化的情况下我的查询通常也需要花费相同的时间来执行。 将其更改为使用缓存的ExecutionEngine可以看到我的查询时间工作表的下半部分在缓存后下降了0到1毫秒这是非常出色的进步。   现在从最坏的情况开始进入每个查询。 我决定在本地计算机上进行优化仅分配1GB的堆空间并在一个冷图上进行优化。 因此我忽略了缓存后查询执行的改进-我认为这是确保进度的一种更好的方法-如果第一个查询命中没有改善那么您确实没有对其进行优化。 这样如果它在有限的硬件上确实能很好地工作我对它在生产中可以更好地工作充满信心。   除了在代码中安排查询时间之外我还使用webadmin控制台进行了优化。 该查询糟糕的指标是它不会返回并且控制台将挂起。 优化以使其不会挂起本身就是一个重大改进。 高度不科学但我建议这样做。   我的第一个查询平均大约76558毫秒该时间是通过在引擎execute方法周围添加开始时间和结束时间而获得的。 第一次优化后它减少到466ms。 这是原始查询 https : //gist.github.com/4436272   这是经过优化的一个 https ://gist.github.com/4436281无需执行此大型匹配只是为了基于a的alertDate属性过滤出结果因此我减少了匹配以返回最小的集合首先可以过滤的数据即 通往的道路  如果要在第一次匹配之前执行错误查询则会看到返回2万行之类的信息。 过滤后它们只有450个奇数行。 可以想象第二个查询Swift减少了您可能使用的结果数量。   第二个变化是我那天从迈克尔那里学到的东西当时我问做大型比赛还是继续修剪子查询是否有意义。 他的回答是“ 问题是您是在使用match来通过描述模式来实际扩展结果集还是只是想确定某些关系存在或不存在即过滤。 如果是后者则可能要在where子句中使用path-expression语法。  WHERE a-[:FOO]-b
or WHERE NOT(a-[:FOO]-b) 这花了一点时间来适应因为我编写MATCH子句的方式恰恰是我脑海中的想法但是现在我可以区分出所需结果的匹配项与过滤器的匹配项了。 在上面的查询中我的结果中需要ir因此无需在匹配中包含a-[alert_for_inspection]-i 我可以在WHERE中使用它来确保a确实与i有关。   这是另一个示例 https : //gist.github.com/4436293   立刻您会看到我们按日期过滤了cm关系-如果它们不在日期范围内则无需我们先进行匹配。 因此查询的这一部分可以重写为  start cnode: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} 在那之后下一个过滤器处于相同的原理  with cm
match (cm)-[:cycle_metric] -m-[:metric_activity] -ma-[:metric_unit] - (u)-[:alert_for_unit]-(a) where a.alertDatecm.measureDate and a.fromEntityType{type} 这进一步修剪了我们的结果集。 最后将连接添加到r以得到我们的结果确保不会导致r产生但必不可少的路径进入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原始时间-33360毫秒经过优化-246毫秒。   至少对我来说我的大多数查询都属于这种模式因此到第二天我就能够非常快速地重构它们。 有趣的是在此之后我仍然感到响应缓慢但是在日志中打印的查询时间很小。 消除之后我发现我的代码在执行查询之后由executionEngine.execute实际上停留了很长时间但在结果集的第一次迭代中。我假设结果不一定在execute方法期间收集但在结果集的迭代中比较懒惰-我不了解Cypher内部结构因此我可能完全错了。 但是定时迭代本身可以指出更差的查询。   其他点点滴滴-ORDER BY增加了很多时间。 如果没有它您应该放下第一件事。 DISTINCT还增加了时间但是在我的许多情况下很难删除它。   如果要检查是否缺少可选路径通常在哪里进行MATCHu-[rhas_a]-aWHERE NOTr为null而是改写为MATCHu-[ other_stuff]-.. WHERE NOTu-[has_a] -a的效果要好得多。 但是在我有诸如MATCH X- [ooptional] -Y WHERE存在o将Y匹配到A和B或OR不存在o将X匹配到c和d的可选路径的地方我无法简化与没有可选路径的其他查询相比这些查询仍需要一些时间。   最终-该问题被发现得太晚了因为测试数据从未与实时数据非常接近。 图的结构起着很大的作用-一些节点是紧密连接的而其他节点则不是很多-并且涉及那些紧密连接的节点的查询是对我们最大的伤害。 尽可能尝试使用生产质量数据进行性能测试或者尝试创建与之类似的测试数据。   因此总结一下   始终参数化您的查询  缓存ExecutionEngine  找出要过滤的内容并尽早在涉及的匹配最少的情况下应用该过滤器以便在进一步查询时结果集逐渐变小。 继续测量每个子查询中返回的时间和结果以便您可以确定过滤器不明显时先执行的操作  检查您的MATCH和RETURN子句-在MATCH中仅包括RETURN所需的那些部分。 剩下的将用于过滤结果的信息可以进入WHERE  如果您不需要ORDER BY请昨天放下  如果您不需要DISTINCT也要摆脱它  如果不需要基于可选路径的检查可以将检查是否存在可选路径从MATCH移到WHERE  不仅要花费查询的execute还要花费时间迭代结果  如果您的Webadmin控制台挂起则说明您做的不好。 删除查询的各个部分以找出有问题的部分。  尝试尽可能使用实时数据  在资源不佳的冷图上进行测试-当您看到生产中的图形滑过您时您会感觉好多了    参考 Thought Bytes博客上来自我们JCG合作伙伴 Aldrin和Luanne Misquitta的优化Neo4j Cypher查询 。  翻译自: https://www.javacodegeeks.com/2013/01/optimizing-neo4j-cypher-queries.html