搜索索引

<ph type="x-smartling-placeholder">

本页面介绍了如何向表中添加搜索索引。 搜索索引是为 允许在 Google Cloud 中进行全文搜索 Spanner。

全文搜索索引

您可以在要创建的任何列上创建搜索索引 支持全文搜索。要创建搜索索引,请使用 CREATE SEARCH INDEX DDL 语句,或使用 ALTER SEARCH INDEX DDL 语句。Spanner 自动构建和维护搜索索引,包括添加和 在搜索索引中的数据发生变化时立即对其进行更新。

搜索索引可进行分区未分区,具体取决于类型 您希望加速的查询的数量。

  • 分区索引是最佳选择的一个示例是, 应用查询电子邮件邮箱。每个查询都被限制 邮箱。

  • 例如,当未分区查询是最佳选择时, 同一商品清单中的所有商品类别都有一项查询。

除全文搜索外,Spanner 搜索索引还支持 以下:

  • 子字符串搜索,这是一种用于查找较短时间的 字符串(子字符串)。
  • 加速包含数字和完全匹配表达式的查询。
  • 将任何索引数据子集的条件组合到单个索引扫描中。

搜索索引支持使用非文本数据,例如数字和 完全匹配字符串,那么搜索索引最常见的用例是将 文本。

为了显示搜索索引的功能,我们假设有一个表, 存储有关音乐专辑的信息:

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  AlbumTitle STRING(MAX)
) PRIMARY KEY(AlbumId);

Spanner 提供了多个标记化函数, 词元。要修改上表,以便用户运行全文搜索来查找 使用 TOKENIZE_FULLTEXT 函数从影集标题创建词元 专辑标题。然后,创建一个使用 TOKENLIST 数据类型的列 来保存 TOKENIZE_FULLTEXT 的标记化输出。在本示例中 我们创建 AlbumTitle_Tokens 列。

ALTER TABLE Albums
  ADD COLUMN AlbumTitle_Tokens TOKENLIST
  AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN;

以下代码使用 CREATE SEARCH INDEX DDL 创建搜索索引 (AlbumsIndex) 对 AlbumTitle 令牌 (AlbumTitle_Tokens):

CREATE SEARCH INDEX AlbumsIndex
  ON Albums(AlbumTitle_Tokens);

添加搜索索引后,使用 SQL 查询查找匹配的影集 搜索条件。例如:

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")

数据一致性

创建索引时,Spanner 会使用自动化流程 回填数据以确保一致性。当提交写入时,索引 会在同一事务中进行更新Spanner 自动 执行数据一致性检查。

搜索索引架构定义

搜索索引在表的一个或多个 TOKENLIST 列上定义。搜索 索引包含以下组成部分:

  • 基表:需要编入索引的 Spanner 表。
  • TOKENLIST:用于定义令牌的一系列列 需要编入索引的内容这些列的顺序并不重要。

例如,在以下语句中,基表为 Albums。TOKENLISTAlbumTitle (AlbumTitle_Tokens) 和 Rating 中创建列 (Rating_Tokens)。

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  SingerId INT64 NOT NULL,
  ReleaseTimestamp INT64 NOT NULL,
  AlbumTitle STRING(MAX),
  Rating FLOAT64,
  AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN,
  Rating_Tokens TOKENLIST AS (TOKENIZE_NUMBER(Rating)) HIDDEN
) PRIMARY KEY(AlbumId);

使用以下 CREATE SEARCH INDEX 语句,通过 AlbumTitleRating 的令牌创建搜索索引:

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens, Rating_Tokens)
PARTITION BY SingerId
ORDER BY ReleaseTimestamp DESC

搜索索引具有以下选项:

  • Partitions:用于划分搜索索引的一组可选列。 查询分区索引的效率通常要远远高于 查询未分区索引。如需了解详情,请参阅 分区搜索索引
  • 排序顺序列:可选的 INT64 列, 用于建立从搜索索引中检索的顺序。有关 请参阅 搜索索引排序顺序
  • 交错:与二级索引一样,您可以交错搜索索引。 交错搜索索引使用更少的资源来写入和联接 基表。如需了解详情,请参阅交错搜索 索引
  • 选项子句:覆盖默认值的键值对列表 搜索索引的设置。

如需了解详情,请参阅 CREATE SEARCH INDEX 参考文档。

搜索索引的内部布局

搜索索引的内部表示形式的一个重要元素是 docid,可高效存储主键 基表的值(可以是任意长度)。它也是 内部数据布局的先后顺序(根据用户提供的 ORDER BY) 列的 CREATE SEARCH INDEX 子句。它的表示形式为 两个 64 位整数。

搜索索引在内部以两级映射的形式实现:

  1. Docid 的令牌
  2. 文档 ID 转换为基表主键

与 Spanner 相比,该方案可节省大量存储空间 因此无需为每个对象存储完整的基表主键 <token, document> 对。

有两种类型的物理索引,可以实现两个级别的 映射:

  1. 将分区键和 Docid 映射到基表的二级索引 主键。在上一部分中的示例中,这会将 {SingerId, ReleaseTimestamp, uid} 映射到 {SingerId, AlbumId}。二级索引还会 存储 CREATE SEARCH INDEXSTORING 子句中指定的所有列。
  2. 词元索引将词元映射到 Docid,类似于 信息检索文献。Spanner 提供 搜索索引的每个 TOKENLIST 使用单独的词元索引。从逻辑上来说 词元索引维护每个分区内每个词元的 Docid 列表 (在信息检索中称为“帖子列表”)。这些列表按顺序排列 令牌用于快速检索,而在列表中, docid 用于排序。 各个词元索引是一个实现细节,不会通过 Spanner API。

Spanner 支持以下四个 Docid 选项。

搜索索引 文档 ID 行为
搜索索引省略了 ORDER BY 子句 { uid } Spanner 会添加一个隐藏的唯一值 (UID) 来标识每一行。
ORDER BY column { column, uid } Spanner 会将 UID 列添加为分区中具有相同 column 值的行之间的裁定程序。
ORDER BY column ... OPTIONS (disable_automatic_uid_column=true) { column } 系统不会添加 UID 列。column 值在分区中必须是唯一的。
ORDER BY column1, column2 ... OPTIONS (disable_automatic_uid_column=true) { column1, column2 } 系统不会添加 UID 列。column1column2 值的组合在分区中必须是唯一的。

使用说明:

  • 内部 UID 列不通过 Spanner 公开 API。
  • 在未添加 UID 的索引中,如果发生事务,则任何事务都将失败 会生成两个具有相同(分区、排序顺序)的行。

例如,请考虑以下数据:

AlbumId SingerId ReleaseTimestamp AlbumTitle
a1 1 997 大狗
a2 1 743 大型猫科动物

假设 presort 列按升序排列,则词元的内容为 由 SingerId 分区的索引对 方式:

SingerId _token ReleaseTimestamp uid
1 743 uid1
1 997 uid2
1 743 uid1
1 997 uid2

搜索索引分片

使用 Spanner 时, 对表进行拆分 分布搜索索引数据,以便特定基表行中的所有令牌 在同一个分块中换句话说,搜索索引是文档分片的。 这种分片策略会对性能产生重大影响:

  1. 与每项事务通信的服务器数量 常量,而不考虑词元数量或编入索引的 TOKENLIST 列。
  2. 会执行涉及多个条件表达式的搜索查询 每个分块都独立运行,避免了与 使用分布式联接。

搜索索引有两种分布模式:

  • 统一分片(默认)。在统一分片中,每个 基表行随机分配给分区的索引分块。
  • 排序顺序分片。在排序顺序分片中,每个基表行的数据 根据 ORDER BY 分配给分区的索引分块 列。 例如,如果选择的是降序排序顺序,则包含 最高的排序顺序值出现在分区的第一个索引分块上, 以及下一个分块中的次高排序顺序值组。

这些分片模式需要权衡热点风险和 查询费用:

  • 排序顺序分片搜索索引在索引 已按时间戳排序有关详情,请参阅选择主键以 阻止 热点。 另一方面,如果一系列文档的写入负载增加, 均匀分片可确保增加量在 处理。
  • 基于负载的标准拆分会创建额外的分块, 并充分防范了出现热点问题。统一分片的缺点是 以便它可以针对某些类型的查询使用更多资源。

搜索索引的分片模式使用 OPTIONS 子句进行配置:

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens, Rating_Tokens)
PARTITION BY SingerId
ORDER BY ReleaseTimestamp DESC
OPTIONS (sort_order_sharding = true);

设置 sort_order_sharding=false 或未指定时,搜索索引为 使用统一分片创建而成。

交错搜索索引

与二级索引一样,您可以在以下位置交错搜索索引: 基表的父表。使用交错搜索的主要原因 索引是将基表数据与小型分区的索引数据共置的。 这种机会性主机托管具有以下优势:

  • 写入不需要执行两阶段提交
  • 搜索索引与基表的后联接不是分布式。

交错搜索索引具有以下限制:

  1. 排序顺序分片 索引 它们可以交错
  2. 搜索索引只能在顶级表(而不是子表)中交错 表)。
  3. 与交错表和二级索引一样, 父表是交错式中 PARTITION BY 列的前缀 搜索索引。

以下示例演示了如何定义交错搜索索引:

CREATE TABLE Singers (
  SingerId INT64 NOT NULL
) PRIMARY KEY(SingerId);

CREATE TABLE Albums (
  SingerId INT64 NOT NULL,
  AlbumId STRING(MAX) NOT NULL,
  AlbumTitle STRING(MAX),
  AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN
) PRIMARY KEY(SingerId, AlbumId),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens)
PARTITION BY SingerId
INTERLEAVE IN Singers
OPTIONS (sort_order_sharding = true);

过滤后的 NULL 搜索索引

搜索索引可以使用 WHERE column IS NOT NULL 语法 排除基表中的行。NULL 过滤可以应用于分区键,排序 对列和存储列进行排序。不对存储的数组列执行 NULL 过滤 允许。

示例

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens)
STORING Genre
WHERE Genre IS NOT NULL

查询必须指定 NULL 过滤条件(Genre IS NOT NULL )。WHERE否则,查询优化工具将无法 使用搜索索引。如需了解详情,请参阅 SQL 查询要求

对生成的列使用 NULL 过滤,以根据任意结果排除行 任意条件。有关详情,请参阅使用 生成的列

后续步骤