搜索索引可以将多个词元化列编入索引,从而提高对这些列的查询效率。本页面介绍了如何对多个列执行搜索,这是一种全文搜索类型。
执行多列搜索
搜索索引的结构可确保查询不需要分布式联接,从而确保查询的性能可预测。由于与基表行对应的所有 token 都位于同一分块上,因此避免了分布式联接。
例如,请考虑以下架构:
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_Tokens
和 Studio_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')
您还可以在同一查询中将使用搜索索引加速的非文本条件与全文搜索函数搭配使用。
后续步骤
- 了解全文搜索查询。
- 了解如何对搜索结果进行排名。
- 了解如何执行子字符串搜索。
- 了解如何对搜索结果进行分页。
- 了解如何混合使用全文查询和非文本查询。