【发布时间】:2023-03-25 02:20:01
【问题描述】:
我将 MySQL 数据库迁移到 Neo4j 并测试了一个简单的请求。我很惊讶地看到,neo4j 中的等效请求比 MySql 中长 10 到 100 倍。我正在开发 Neo4j 2.0.1。
在原始 MySql 架构中,我有以下三个表:
- 国家/地区:包含一个“代码”、一个“大陆 ID”和一个“选定”布尔值,
- 城市:包含一个“country_code”、一个“name”和一个“status”布尔值,
- 剧院:包含一个“city_id”和一个“public”布尔值,
每个属性都有一个索引。我想在几个条件下按城市显示给定大陆的剧院数量。请求是:
SELECT count(*) as nb, c.name
FROM `cities` c LEFT JOIN theaters t ON c.id = t.city_id
WHERE c.country_code IN
(SELECT code FROM countries WHERE selected is true AND continent_id = 4)
AND c.status=1 AND t.public = 1
GROUP BY c.name ORDER BY nb DESC
Neo4j 中的数据库架构如下:
(:Continent)-[:Include]->(:Country{selected:bool})-[:Include]->(:City{name:string, status:bool})-[:Include]->(:Theater{public:bool})
还为每个属性定义了一个索引。密码请求是:
MATCH (:Continent{code: 4})-[:Include]->(:Country{selected:true})-[:Include]->(city:City{status:true})-[:Include]->(:Theater{public: true})
RETURN city.name, count(*) AS nb ORDER BY nb DESC
每个数据库中大约有 70.000 个城市和 140.000 个剧院。
在 ID 为 4 的大陆上,MySql 请求大约需要 0.02 秒,而 Neo4j 需要 0.4 秒。此外,如果我在 Cypher 请求中引入 Country 和 City (...(:Country{selected:true})-[:Include*..3]->(city:City{status:true})...) 之间的可变关系长度,因为我希望能够添加像 Regions 这样的中间级别,那么请求需要超过 2 秒。
我知道在这种特殊情况下,使用 Neo4j 代替 MySql 没有任何好处,但我希望看到这两种技术之间的性能大致相当,并且我想利用 Neo4j 地理层次结构功能。
是我遗漏了什么还是 Neo4j 的限制?
感谢您的回答。
编辑:首先你会找到数据库转储文件here。 Neo4j server configuration 是开箱即用的。我在 Ruby 环境中工作,我使用的是neography gem。我也单独运行 Neo4J 服务器 因为我不在 JRuby 上,所以它通过 Rest API 发送密码请求。
该数据库包含 244 个国家、69000 个城市和 138,000 家影院。对于continent_id 4,有46,982 个城市(37,210 个将状态布尔值设置为true)和74,420 个剧院。
请求返回 2256 行。在第三次运行时,花了 338 毫秒。这是带有分析信息的请求输出:
profile MATCH (:Continent{code: 4})-[:Include]->(country:Country{selected:true})-[:Include*..1]->(city:City{status:true})-[:Include]->(theater:Theater{public: true}) RETURN city.name, count(*) AS nb ORDER BY nb DESC;
==> ColumnFilter(symKeys=["city.name", " INTERNAL_AGGREGATE85ca19f3-9421-4c18-a449-1097e3deede2"], returnItemNames=["city.name", "nb"], _rows=2256, _db_hits=0)
==> Sort(descr=["SortItem(Cached( INTERNAL_AGGREGATE85ca19f3-9421-4c18-a449-1097e3deede2 of type Integer),false)"], _rows=2256, _db_hits=0)
==> EagerAggregation(keys=["Cached(city.name of type Any)"], aggregates=["( INTERNAL_AGGREGATE85ca19f3-9421-4c18-a449-1097e3deede2,CountStar())"], _rows=2256, _db_hits=0)
==> Extract(symKeys=["city", " UNNAMED27", " UNNAMED7", "country", " UNNAMED113", "theater", " UNNAMED72"], exprKeys=["city.name"], _rows=2257, _db_hits=2257)
==> Filter(pred="(hasLabel(theater:Theater(3)) AND Property(theater,public(5)) == true)", _rows=2257, _db_hits=2257)
==> SimplePatternMatcher(g="(city)-[' UNNAMED113']-(theater)", _rows=2257, _db_hits=4514)
==> Filter(pred="(((hasLabel(city:City(2)) AND hasLabel(city:City(2))) AND Property(city,status(4)) == true) AND Property(city,status(4)) == true)", _rows=2257, _db_hits=74420)
==> TraversalMatcher(start={"label": "Continent", "query": "Literal(4)", "identifiers": [" UNNAMED7"], "property": "code", "producer": "SchemaIndex"}, trail="( UNNAMED7)-[ UNNAMED27:Include WHERE (((hasLabel(NodeIdentifier():Country(1)) AND hasLabel(NodeIdentifier():Country(1))) AND Property(NodeIdentifier(),selected(3)) == true) AND Property(NodeIdentifier(),selected(3)) == true) AND true]->(country)-[:Include*1..1]->(city)", _rows=37210, _db_hits=37432)
【问题讨论】:
标签: neo4j