在搜索索引中搜索多个列

搜索索引可以为多个经过令牌化处理的列编制索引,从而提高对这些列的查询效率。本页介绍了如何对多列执行搜索,这是一种全文搜索

搜索索引的结构可确保查询不需要分布式联接,从而确保查询的性能可预测。由于与基表行对应的所有令牌都位于同一分块上,因此可以避免分布式联接。

例如,请考虑以下架构:

GoogleSQL

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  Title STRING(MAX),
  Studio STRING(MAX),
  Title_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Title)) HIDDEN,
  Studio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(Studio)) HIDDEN
) PRIMARY KEY(AlbumId);

CREATE SEARCH INDEX AlbumsIndex ON Albums(Title_Tokens, Studio_Tokens);

PostgreSQL

CREATE TABLE albums (
  albumid character varying NOT NULL,
  title character varying,
  studio character varying,
  title_tokens spanner.tokenlist
      GENERATED ALWAYS AS (TOKENIZE_FULLTEXT(title)) VIRTUAL HIDDEN,
  studio_tokens spanner.tokenlist
      GENERATED ALWAYS AS (TOKENIZE_FULLTEXT(studio)) VIRTUAL HIDDEN,
) PRIMARY KEY(albumid);

CREATE SEARCH INDEX albumsindex ON albums(title_tokens, studio_tokens);

现在,一个查询可以搜索两个字段:Title_TokensStudio_Tokens

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, "fifth symphony")
  AND SEARCH(Studio_Tokens, "Blue Note Studio")

PostgreSQL

SELECT albumid
FROM albums
WHERE spanner.search(title_tokens, 'fifth symphony')
  AND spanner.search(studio_tokens, 'Blue Note Studio')

Spanner 支持在 WHERE 子句中的联接运算符、析取运算符和否定运算符中使用多列搜索查询。您可以将以下所有类型的查询与搜索索引搭配使用:

  • 联接运算:查找 Title 包含字词“car”且 Studio 包含字词“sun”的文档。

    GoogleSQL

    SELECT AlbumId
    FROM Albums
    WHERE SEARCH(Title_Tokens, 'car') AND SEARCH(Studio_Tokens, 'sun')
    

    PostgreSQL

    SELECT albumid
    FROM albums
    WHERE spanner.search(title_tokens, 'car') AND spanner.search(studio_tokens, 'sun')
    
  • 析取运算:查找 Title 包含“car”一词或 Studio 包含“sun”一词的文档

    GoogleSQL

    SELECT AlbumId
    FROM Albums
    WHERE SEARCH(Title_Tokens, 'car') OR SEARCH(Studio_Tokens, 'sun')
    

    PostgreSQL

    SELECT albumid
    FROM albums
    WHERE spanner.search(title_tokens, 'car') OR spanner.search(studio_tokens, 'sun')
    
  • 否定:查找 Title 不包含“car”一词的所有文档。

    GoogleSQL

    SELECT AlbumId
    FROM Albums
    WHERE NOT SEARCH(Title_Tokens, 'car')
    

    PostgreSQL

    SELECT albumid
    FROM albums
    WHERE NOT spanner.search(title_tokens, 'car')
    

    rquery 语言可以执行相同类型的搜索:

    GoogleSQL

    SELECT AlbumId
    FROM Albums
    WHERE SEARCH(Title_Tokens, '-car')
    

    PostgreSQL

    SELECT albumid
    FROM albums
    WHERE spanner.search(title_tokens, '-car')
    

    这两种形式都会过滤 Title 为 NULL 的文档。令牌化和搜索函数定义为在 NULL 输入时返回 NULL。SQL 将 NOT NULL 定义为 NULL。

此外,您可以多次引用同一 TOKENLIST 列。

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE (SEARCH(Title_Tokens, 'car') OR SEARCH(Studio_Tokens, 'sun'))
  AND (SEARCH(Title_Tokens, 'guy') OR SEARCH(Studio_Tokens, electric))

PostgreSQL

SELECT albumid
FROM albums
WHERE (spanner.search(title_tokens, 'car') OR spanner.search(studio_tokens, 'sun'))
  AND (spanner.search(title_tokens, 'guy') OR spanner.search(studio_tokens, 'electric'))

您可以使用 rquery 语言或 SQL 在同一列中搜索多个字词。建议使用 rquery,因为它可以高效地对参数化查询进行缓存。除了查询缓存命中率更高之外,rquery 和 SQL 语言的延迟时间和性能率相同。

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, 'car OR guy')

SELECT AlbumId
FROM Albums
WHERE SEARCH(Title_Tokens, 'car') OR SEARCH(Title_Tokens, 'guy')

PostgreSQL

SELECT albumid
FROM albums
WHERE spanner.search(title_tokens, 'car OR guy')

SELECT albumid
FROM albums
WHERE spanner.search(title_tokens, 'car') OR spanner.search(title_tokens, 'guy')

您还可以在同一查询中将使用搜索索引加速的非文本条件与全文搜索函数结合使用。

后续步骤