将显式 Lucene 索引迁移到原生 Schema 索引
鉴于一些客户仍在使用旧版 Neo4j 版本,这些版本使用旧版/显式索引,我们将在本文档中讨论一些关于在升级到 Neo4j 4.x 版本时如何将这些索引转换为原生 Schema 索引的要点,因为旧版/显式索引从 3.5.x 版本开始已弃用,并在 4.x 版本中完全移除。
背景信息:在 Neo4j 3.2(2017 年发布)之前,旧版/显式索引是唯一可用的索引类型。这些早期版本的索引是在幕后通过 Lucene 实现的,通常会导致写入性能显著下降,因此需要用 3.3 及更高版本中提供的原生 Schema 索引替换它们。
除了性能方面,同样重要的是,在通过 Java API(以及从 3.3.x 版本开始的存储过程)添加/删除/更新节点/关系/属性时,还必须显式/手动地维护显式索引的最新状态,因此它们被称为显式索引。
相反,原生索引会自动维护,因此无需任何此类手动步骤和/或额外代码来保持其最新状态。
从实现的角度来看,这些旧版索引没有列出很多 Schema 详情,除了索引创建时原始作者选择的命名约定之外,没有太多有用的线索可以帮助以脚本方式实现将这些索引迁移到 Neo4j 的原生 Schema 索引的自动化过程。
因此,任何索引迁移都必须逐个索引进行,并且可能涉及一定程度的猜测。这意味着您必须查看 API 代码并评估哪些节点或关系属性被索引,并相应地在这些属性上实现补充 Schema 索引,或者查看 Cypher 查询并想出支持的索引来优化其执行。
总体而言,在较高层次上,以下是推荐的方法
1) 获取现有版本上所有索引的列表
-
例如:在 3.x 中,您可以使用 "call db.index.explicit.list();",它将显示索引名称及其类型(可以是“精确”或“全文”),以及它是节点索引还是关系索引,这将帮助您确定要构建哪种类型的 Schema 索引。
2) 接下来查看您的 Cypher 和/或 Java API 代码,并将其相应地转换为 4.x+ 格式。
-
例如,将 “start” 语句转换为等效的 Match 语句。示例
-
START n=node:myExplicitIndexYear("myid:1234567") RETURN n;
-
上述查询将更改为以下内容
-
MATCH (n:Person{myid:1234567}) RETURN n;
-
3) 实现您需要支持并优化步骤 2 中关联/转换的查询执行的等效 Schema 索引。
-
例如: CREATE INDEX index_name FOR (n:Person) ON (n.myid);
-
更具体地说
-
检查所有 Cypher 查询以了解它们实际写入该索引的内容,并推导出 create index(对于整数、字符串、日期、地理空间等)和/或 call db.index.fulltext.createIndexForNodes(FTS)语句。
-
检查所有读取该索引的操作,并采用语句以使用新索引(这意味着启用查询日志记录以捕获生成的 Cypher 查询及其性能属性,例如执行时间与 IO 与内存与 CPU,以标记最长运行的查询以逐个进行故障排除 - 并且很有可能您的查询模式彼此相似,因此,一旦一个查询修复,它也将类似地帮助其他类似的查询)。
-
4) 完成所有显式索引后,关闭数据库并移动/删除关联的索引子文件夹(例如 /data/databases/graph.db/index)。
请注意,如果碰巧将旧版索引转换为等效的 Schema 索引后,使用旧版索引的搜索查询返回的行数意外(与 Schema 索引相比),则这可能表示 Schema 索引可能定义不正确(在错误的标签:属性上),或者旧版索引未更新(请记住,旧版索引必须手动保持最新,因此,例如,如果您的 Java API 代码中没有适当的错误处理,则完全有可能由于任何原因(例如服务器重启等)导致回滚时事务未正确重试和应用提交)。这是一个 3.x 示例,演示了这种情况
// Create New Nodes
//
CREATE (p:Person {name:'Steve_1',year:1990});
CREATE (p:Person {name:'Steve_2',year:1990});
CREATE (p:Person {name:'Steve_3',year:1990});
// Create Two Explicit Indexes(also called Legacy/Manual/Lucene Indexes)
//
CALL db.index.explicit.forNodes('myExplicitIndexFTS', {type: 'fulltext', provider: 'lucene'});
CALL db.index.explicit.forNodes('myExplicitIndexYear', {type: 'exact', provider: 'lucene'});
// List Explicit Indexes
//
call db.index.explicit.list;
// Index nodes with name property
//
MATCH (p:Person{name:'Steve_1'}) call db.index.explicit.addNode('myExplicitIndexFTS', p, 'name', 'Steve_1') yield success return count(*);
MATCH (p:Person{name:'Steve_2'}) call db.index.explicit.addNode('myExplicitIndexFTS', p, 'name', 'Steve_2') yield success return count(*);
// Index nodes with "birth year" property
//
match (p:Person{name:'Steve_1'})
with p
call db.index.explicit.addNode("myExplicitIndexYear",p,"year",p.year) yield success return count(*);
// Search for persons with matching name VE, which will only return Steve_1, and Steve_2
//
CALL db.index.explicit.searchNodes('myExplicitIndexFTS','name:*VE*');
// Search for persons with year=1990 which will only return Steve_1
//
CALL db.index.explicit.searchNodes('myExplicitIndexYear','year:1990');
// Search for persons with year=1990 using explicit index which will only return Steve_1
//
start n=node:myExplicitIndexYear("year:1990") return n;
// Convert "start" to equivalent Match statement, and this statement returns all 3 rows corresponding to year=1990 (and of course ideally, you would want to create an index on :Person(
year) or :Person(name) for best performance when creating equivalent native schema indexes on these two properties.
match (n:Person{year:1990}) return n;
附录
-
有关每个版本已弃用功能的完整列表,请访问以下链接: https://neo4j.ac.cn/docs/cypher-manual/current/deprecations-additions-removals-compatibility/
-
如上所述,3.3.x 还提供了使用存储过程的显式索引实现,以使其更容易实现而无需诉诸于使用 Java API,但是,这些也必须手动维护。此外,这些过程集从 3.5.x 版本开始也已弃用,并在 4.0、4.1、4.2 中被一组新的过程(仅用于全文搜索用例)所取代,如本文档中所述: https://neo4j.ac.cn/docs/cypher-manual/current/administration/indexes-for-full-text-search/
-
此外,根据 4.3.0 版本变更日志,所有 FTI 过程均已弃用。
-
"引入 CREATE FULLTEXT INDEX… Cypher 命令。弃用 db.index.fulltext.createNodeIndex、db.index.fulltext.createRelationshipIndex 和 db.index.fulltext.drop。"。
-
-
需要修改/删除的 3.x 之前 Java API 代码的文档
此页面是否有帮助?