索引查询会降低查询性能

时间:2018-07-25 09:02:31

标签: neo4j cypher neo4j-apoc

我试图在一个查询中使用索引,以使其运行更快,但使另一个查询运行缓慢。所以我对数据处理有一个查询?使用索引运行速度更快,而使用Neo4j(使用Kafka)生产数据的速度更快,而使用索引运行的速度则较慢。我需要在数据处理之前执行索引创建,并在需要生成数据时将其删除,但这不是一种有效的技术。 Neo4j查询如何实际使用索引运行得更慢?

这是数据产生的查询:

import * as express from 'express';

const router = express.Router();
router.post('/a/x', (req, res) => {
    // Your code
});

**OR**

var router = require('./router.js')


app.use('/v1', router); // HERE you can specify version if you want or / for nothing

不带索引的查询的性能:

documentation

6432058在1888毫秒内总共命中了数据库

具有索引的查询的配置文件计划:

enter image description here

138425061在149617毫秒内的总数据库点击次数

索引查询如下:

 MATCH (m:Member)-[mtg_r:MT_TO_MEMBER]->(mt:MemberTopics)-[mtt_r:MT_TO_TOPIC]->(t:Topic), (t1:Topic)-[tt_r:GT_TO_TOPIC]->(gt:GroupTopics)-[tg_r:GT_TO_GROUP]->(g:Group)-[h_r:HAS]->(e:Event)-[a_r:AT]->(v:Venue) 
WHERE mt.topic_id = gt.topic_id AND distance(point({ longitude: m.lon, latitude: m.lat}),point({ longitude: v.lon, latitude: v.lat })) < 4000 
RETURN distinct mt.member_id as member_id, m.lat as member_lat, m.lon as member_lon

1 个答案:

答案 0 :(得分:1)

索引查询的性能较差的原因是因为Cypher计划程序在提交的工作量(估算的行数与实际的行数)上有误。

没有索引,计划者就知道必须对MemberTopics进行标签扫描,并且内部统计数据表明,这将达到约300万行(这是正确的)。根据Membertopics的索引,计划者的内部统计数据表明,如果使用索引,则可能需要约2k行,而实际结果是约7000万行...哎呀!这部分是因为计划人员低估了查询的这一点将处理多少行,但是我不确定为什么它要偏离这么多数量级。如果您从密码中删除Member节点,然后将返回值更改为RETURN *,则看来您将获得该问题的答案。


部分原因是您的密码/数据本身是要计划的怪物。

  • 您匹配2个其他地方未使用的Topic节点(t和t1)
  • WHERE mt.topic_id = gt.topic_idforeign key的引用,绝不能出现在密码中;确实是您表现出色的关键所在。 topic_id应该是它自己的节点,或者您应该在mt和gt之间具有直接关系。 Neo4j确实擅长于走人际关系。外键很糟糕(与沿关系走相比)。
    • 您有2条漫长的路,没有明确说明它们之间的关系(从Cypher计划者的角度来看)。
  • 您的MATCH是一对没有明确起点的长链。不会保证将一个节点锁定到特定(几个)节点的长路径几乎可以保证爆炸性的查询行数,从而提高性能。

关于您可以做什么,

  • 限制查询范围

到单个成员,组或区域

  • 使用WITH将查询分为多个阶段

With将创建Cypher的逻辑分区,并且计划者在继续其余逻辑之前,通常会尝试解析WITH之前的所有内容。您比计划者更了解数据,因此这是一种在不更改结果的情况下限制查询范围的好方法。 (在您的情况下,可能仅从成员和地点开始,然后从那里进行过滤。)

  • 不要使用外键

用关系或中间节点替换mt.topic_id = gt.topic_id