知识库

索引限制和解决方法

在本文中,我们将讨论索引提供程序以及存在的限制和解决方法。

Neo4j 中有两种索引类型:btree 和 full-text。本文主要介绍 btree 索引,在 4.0 版本之前被称为 schema 索引。这是您通过 Cypher 创建索引或索引支持的约束时获得的常规索引。

查询
CREATE INDEX "My index" FOR (p:Person) ON (p.name)

所有索引都由索引提供程序支持。Full-text 索引由 fulltext-1.0 支持,btree 索引由 native-btree-1.0(默认)或 lucene+native-3.0 支持。

下表列出了可用的 btree 索引提供程序及其对原生索引的支持

索引提供程序 原生索引支持的值类型

native-btree-1.0

支持所有类型的原生索引

lucene+native-3.0

Lucene 用于单属性字符串,其余使用原生索引

键大小限制

native-btree-1.0 索引提供程序具有 8167 字节的键大小限制。此限制会以不同的方式表现出来,具体取决于键是包含单个字符串、单个数组还是多个值(即,该键是否属于复合索引)。

如果事务中的一项或多项更改达到键大小限制,该事务将在提交任何更改之前失败。如果在索引填充期间达到限制,则生成的索引将处于失败状态,因此无法用于任何查询。

有关如何计算原生索引键大小的详细信息,请参见下文。

如果键超出此限制,则 full-text 索引更可能适合该用例;如果不是这种情况,则 lucene+native-3.0 的键大小限制为 32766 字节。

包含和结束于查询

native-btree-1.0 索引提供程序对 ENDS WITHCONTAINS 查询的支持有限。这些查询无法像使用 STARTS WITH=<> 的查询那样执行优化搜索。相反,索引结果将是带有过滤的索引扫描流。

对于单属性字符串,可以使用支持 ENDS WITHCONTAINSlucene+native-3.0 代替。

要创建使用非默认提供程序的索引,最简单的方法是使用 db.createIndexdb.createUniquePropertyConstraintdb.createNodeKey 过程,您可以向这些过程提供索引提供程序名称。另一种选项是使用 dbms.index.default_schema_provider 配置默认索引提供程序。请注意,此配置选项需要重启才能生效。

键大小计算

这部分描述了如何计算原生索引的键大小。

如关于键大小的章节所述,使用 native-btree-1.0 索引提供程序时,键大小存在限制。本附录详细描述了如何计算大小。

元素大小计算

了解如何计算单个值的大小对于计算最终键的总大小非常有用。在某些情况下,条目大小会因其是否在数组中而异。

表 1. 元素大小
类型 elementSizeifSingle * elementSizeifInArray **

Byte

3

1

Short

4

2

Int

6

4

Long

10

8

Float

6

4

Double

10

8

Boolean

2

1

Date

9

8

Time

13

12

LocalTime

9

8

DateTime

17

16

LocalDateTime

13

12

Duration

29

28

Period

29

28

Point (笛卡尔)

28

24

Point (笛卡尔 3D)

36

32

Point (WGS-84)

28

24

Point (WGS-84 3D)

36

32

String

3 + utf8StringSize ***

2 + utf8StringSize ***

Array

不支持嵌套数组

* elementSizeifSingle 表示元素作为单个条目时的大小。

** elementSizeifInArray 表示元素作为数组的一部分时的大小。

*** utf8StringSizeString 用 UTF8 编码后的字节大小。

elementSizeArray 是数组元素的大小,使用以下公式计算:

  • 如果数组的数据类型是数值类型

    elementSizeArray = 4 + ( arrayLength * elementSizeifInArray )

  • 如果数组的数据类型是几何类型

    elementSizeArray = 6 + ( arrayLength * elementSizeifInArray )

  • 如果数组的数据类型是非数值类型

    elementSizeArray = 3 + ( arrayLength * elementSizeifInArray )

字符串 UTF8 编码

值得注意的是,字母、数字和某些符号等常用字符通常每个字符转换为一个字节。非拉丁字符可能占用多个字节。因此,例如,一个包含 100 个字符或更少的字符串,如果包含多字节字符,其长度可能会超过 100 字节。

更具体地说,字符串相关的字节长度是使用 UTF8 编码后的长度。

示例 1. 计算字符串在索引中使用时的大小

考虑字符串 His name was Måns Lööv

此字符串有 19 个字符,每个字符占用 1 个字节。此外,还有 3 个字符,每个字符占用 2 个字节,共计增加 6 个字节。因此,String 用 UTF8 编码后的字节大小(即 utf8StringSize)为 25 字节。

如果此字符串是原生索引的一部分,则得到

elementSize = 2 + utf8StringSize = 2 + 25 = 27 字节

示例 2. 计算数组在索引中使用时的大小

考虑数组 [19, 84, 20, 11, 54, 9, 59, 76, 82, 27, 9, 35, 56, 80, 65, 95, 16, 91, 61, 11]。

此数组包含 20 个 Int 类型的元素。由于它们位于数组中,我们需要使用 elementSizeifInArray,对于 Int 类型,其值为 4

应用数值类型数组的公式,我们得到

elementSizeArray = 4 + ( arrayLength * elementSizeifInArray ) = 4 + ( 20 * 4 ) = 84 字节

非复合索引

非复合索引违反大小限制的唯一方式是值是一个长字符串或一个大数组。

字符串

非复合索引中的字符串的键大小限制为 8164 字节。

数组

非复合索引中的数组使用以下公式:

1 + elementSizeArray =< 8167

此处 elementSizeArray 是根据 元素大小 计算的数值。

如果我们反向计算,可以得出每种数据类型的精确数组长度限制。

  • 数值类型的计算公式为 maxArrayLength = FLOOR( ( 8167 - 4 ) / elementSizeifInArray )

  • 非数值类型的计算公式为 maxArrayLength = FLOOR( ( 8167 - 4 ) / elementSizeifInArray )

这些计算得出下表:

表 2. 每种数据类型的最大数组长度
数据类型 maxArrayLength

Byte

8163

Short

4081

Int

2040

Long

1020

Float

2040

Double

1020

Boolean

8164

String

参见 最大数组长度,字符串示例

Date

1020

Time

680

LocalTime

1020

DateTime

510

LocalDateTime

680

Duration

291

Period

291

Point (笛卡尔)

340

Point (笛卡尔 3D)

255

Point (WGS-84)

340

Point (WGS-84 3D)

255

请注意,在大多数情况下,Cypher 处理数字时会使用 LongDouble

类型为 String 的属性是一个特殊情况,因为它们的大小是动态的。下表显示了基于特定字符串大小的数组中最大元素数量。

表 3. 最大数组长度,字符串示例
字符串大小 maxArrayLength

1

2721

10

680

100

80

1000

8

该表可用作参考。例如:如果我们知道数组中的所有字符串都占用 100 字节或更少,那么长度为 80 或更小的数组肯定会符合要求。

复合索引

此限制仅适用于满足以下一个或多个条件的情况:

  • 复合索引包含字符串

  • 复合索引包含数组

  • 复合索引针对许多不同的属性(>50)

我们将复合索引的目标属性称为 slot。例如,索引 :Person(firstName, surName, age) 有三个属性,因此有三个 slot。

在索引中,每个 slot 由一个元素填充。为了计算索引的大小,我们必须知道索引中每个元素的大小,即 elementSize,如前面章节所述计算得出。

以下等式可用于验证特定的复合索引条目是否在范围内。

sum( elementSize ) =< 8167

此处,sum( elementSize ) 是复合键所有元素大小的总和,如 [index-configuration-limitations-element-size-calculations]elementSizeifSingle 所定义。

示例 3. 包含字符串的复合索引大小

考虑一个包含五个字符串的复合索引,每个字符串最大可占用 500 字节。

使用上面的等式,我们得到

sum( elementSize ) = 5 * ( 3 + 500 ) = 2515 < 8167

我们的复合索引完全在范围内。

示例 4. 包含数组的索引大小

考虑一个包含 10 个 Float 类型数组的复合索引,每个数组长度为 250。

首先我们计算每个数组元素的大小。

elementSizeArray = 4 + ( arrayLength * elementSizeifInArray ) = 4 + ( 250 * 4 ) = 1004

然后我们计算复合索引的大小。

sum( elementSizeArray ) = 10 * 1004 = 10040 > 8167

此索引键将超出原生索引的键大小限制。

© . All rights reserved.