笛卡尔积的Neo4j查询优化

时间:2018-04-04 12:52:38

标签: neo4j cypher

我正在尝试实施用户旅程分析解决方案。只需分析哪些用户离开应用程序的屏幕。 为此,我已经建模了这样的数据: blue circles are events (a single activity that contains user and device data). green circles are event types (activity types such as the name of the screen) 我建模单个活动,因为我想索引一些属性。无法在Neo4j中索引关系属性。

使用这个模型,我试图用以下查询编写一个跟随三个连续事件类型的查询:

MATCH (eventType1:EventType {eventName:'viewStart-home'})<--(event:EventNode)
<--(eventType2:EventType{eventName:'viewStart-payment'})  

WITH distinct event.deviceId as eUsers, event.clientCreationDate as eDate

MATCH((eventType2)<--(event2:EventNode)
<--(eventType3:EventType{eventName:'viewStart-screen1'}))

WITH distinct event2.deviceId as e2Users, event2.clientCreationDate as e2Date
RETURN e2Users limit 200000

执行计划如下:

last NodeByLabelScan ruins everything

我无法弄清楚这个过程的原因。你能救我吗?

1 个答案:

答案 0 :(得分:1)

您的查询所做的工作远远超出了需要。

根本不需要第一个WITH子句,因为从未使用过生成的eUserseDate变量。第二个WITH子句不需要生成未使用的e2Date变量。

此外,您可以先为:EventType(eventName)添加索引以加快处理速度:

CREATE INDEX ON :EventType(eventName);

通过这些更改,您的查询配置文件可能更简单,处理速度也会更快。

这是一个更新的查询(应该使用索引在路径的一端快速找到EventType节点,以启动查询):

MATCH (:EventType {eventName:'viewStart-home'})<--(:EventNode)
  <--(:EventType{eventName:'viewStart-payment'})<--(event2:EventNode)
  <--(:EventType{eventName:'viewStart-screen1'})
RETURN distinct event2.deviceId as e2Users
LIMIT 200000;

这是一个备用查询,它使用2个USING INDEX提示告诉规划人员快速找到两个路径末端的:EventType个节点以启动查询。这可能比第一个查询更快:

MATCH (a:EventType {eventName:'viewStart-home'})<--(:EventNode)
  <--(:EventType{eventName:'viewStart-payment'})<--(event2:EventNode)
  <--(b:EventType{eventName:'viewStart-screen1'})
USING INDEX a:EventType(eventName)
USING INDEX b:EventType(eventName)
RETURN distinct event2.deviceId as e2Users
LIMIT 200000;

尝试在数据库中对它们进行概要分析,然后选择最佳的数据库或继续进行调整。