我试图在一个查询中使用索引,以使其运行更快,但使另一个查询运行缓慢。所以我对数据处理有一个查询?使用索引运行速度更快,而使用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
不带索引的查询的性能:
6432058在1888毫秒内总共命中了数据库
具有索引的查询的配置文件计划:
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
答案 0 :(得分:1)
索引查询的性能较差的原因是因为Cypher计划程序在提交的工作量(估算的行数与实际的行数)上有误。
没有索引,计划者就知道必须对MemberTopics进行标签扫描,并且内部统计数据表明,这将达到约300万行(这是正确的)。根据Membertopics的索引,计划者的内部统计数据表明,如果使用索引,则可能需要约2k行,而实际结果是约7000万行...哎呀!这部分是因为计划人员低估了查询的这一点将处理多少行,但是我不确定为什么它要偏离这么多数量级。如果您从密码中删除Member节点,然后将返回值更改为RETURN *
,则看来您将获得该问题的答案。
部分原因是您的密码/数据本身是要计划的怪物。
WHERE mt.topic_id = gt.topic_id
是foreign key的引用,绝不能出现在密码中;确实是您表现出色的关键所在。 topic_id应该是它自己的节点,或者您应该在mt和gt之间具有直接关系。 Neo4j确实擅长于走人际关系。外键很糟糕(与沿关系走相比)。
关于您可以做什么,
到单个成员,组或区域
With将创建Cypher的逻辑分区,并且计划者在继续其余逻辑之前,通常会尝试解析WITH之前的所有内容。您比计划者更了解数据,因此这是一种在不更改结果的情况下限制查询范围的好方法。 (在您的情况下,可能仅从成员和地点开始,然后从那里进行过滤。)
用关系或中间节点替换mt.topic_id = gt.topic_id
。