在neo4j 3.5版本中,增加了对ORDER BY的优化,可以通过本地数据库索引(Native Index)提高排序效率。对于有百万或更多节点的集合,排序性能提高会很显著。
在查询中,若要利用这一特性,具体方法如下:
1、为节点属性定义本地索引: CREATE INDEX ON :LABEL(Property)
属性值的类型可以是任何基本类型,但是Point类型除外。
2、在Cypher查询中对建立索引的节点属性显式使用下面任何过滤条件之一:
- 相等 =
- 区间:> 或 <
- STARTS WITH或ENDS WITH
- 包含:CONTAINS 注意:过滤条件中必须包含有类型的值,这样Cypher编译器才会查找是否有数据库索引可以使用。具体例子见下文。
3、在ORDER BY中对建立索引的节点属性进行排序。
如果Cypher编译器能够使用索引对ORDER BY进行优化,那么EXPLAIN时会看到相应的操作符(operator):
- NodeIndexContainsScan
- NodeIndexSeekByRange 而不会再看到Sort、Top操作符。
否则,只会看到在内存中排序相关的操作符:
- Sort
- Top
例子如下。模型是只包含一种标签Account的节点,其属性有acctid, acctNo, id和ifsc(无索引)。
// 查看已创建的索引 Indexes ON :Account(acctNo) ONLINE ON :Account(acctid) ONLINE ON :Account(id) ONLINE
// ------ 没有在ORDER BY中使用索引的例子 -------
// 条件#1不满足:ifsc属性没有索引 MATCH (n:Account) WHERE n.ifsc CONTAINS ‘00’ RETURN n ORDER BY n.ifsc
// 条件#2不满足:没有过滤条件,无法判断acctid类型 MATCH (n:Account) RETURN n ORDER BY n.acctid
// 条件#2不满足:exists()不支持 MATCH (n:Account) WHERE exists(n.id) RETURN n ORDER BY n.id DESC LIMIT 1
// 条件#3不满足:acctNo没有出现在WHERE子句中 MATCH (n:Account) WHERE n.id > 0 RETURN n ORDER BY n.acctNo
// ------ 在ORDER BY中使用索引得到优化的例子 -------
// 所有条件满足、id属性是整数类型,使用>比较符 MATCH (n:Account) WHERE n.id > 0 RETURN n ORDER BY n.id DESC
// 所有条件满足、acctid是字符串类型,使用STARTS WITH MATCH (n:Account) WHERE n.acctid STARTS WITH ‘000’ RETURN n ORDER BY n.acctid DESC LIMIT 1
进一步提示:如果ORDER BY中的节点属性不需要在过滤条件中出现,为了提高性能,也可以把该属性加入WHERE子句中,并保证其永远为TRUE。例如: // 本例中,n.id的值永远为正 MATCH (n:Account) WHERE n.id > 0 AND n.ifsc CONTAINS 'TT’ RETURN n ORDER BY n.id DESC
在线参考: https://neo4j.com/docs/cypher-manual/current/query-tuning/cypher-index-values-order/