创建索引
为了加速文本搜索,可以创建GIN索引。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | gaussdb=# CREATE SCHEMA tsearch; gaussdb=# CREATE TABLE tsearch.pgweb(id int, body text, title text, last_mod_date date) with(storage_type = ASTORE); gaussdb=# INSERT INTO tsearch.pgweb VALUES(1, 'America is a rock band, formed in England in 1970 by multi-instrumentalists Dewey Bunnell, Dan Peek, and Gerry Beckley.', 'America', '2010-1-1'); gaussdb=# INSERT INTO tsearch.pgweb VALUES(2, 'England is a country that is part of the United Kingdom. It shares land borders with Scotland to the north and Wales to the west.', 'England', '2010-1-1'); gaussdb=# INSERT INTO tsearch.pgweb VALUES(3, 'Australia, officially the Commonwealth of Australia, is a country comprising the mainland of the Australian continent, the island of Tasmania, and numerous smaller islands.', 'Australia', '2010-1-1'); gaussdb=# INSERT INTO tsearch.pgweb VALUES(4, 'Japan is an island country in East Asia.', 'Japan', '2010-1-1'); gaussdb=# INSERT INTO tsearch.pgweb VALUES(5, 'Germany, officially the Federal Republic of Germany, is a sovereign state and federal parliamentary republic in central-western Europe.', 'Germany', '2010-1-1'); gaussdb=# INSERT INTO tsearch.pgweb VALUES(6, 'France, is a sovereign state comprising territory in western Europe and several overseas regions and territories.', 'France', '2010-1-1'); gaussdb=# INSERT INTO tsearch.pgweb VALUES(7, 'Italy officially the Italian Republic, is a unitary parliamentary republic in Europe.', 'Italy', '2010-1-1'); gaussdb=# INSERT INTO tsearch.pgweb VALUES(8, 'India, officially the Republic of India, is a country in South Asia.', 'India', '2010-1-1'); gaussdb=# INSERT INTO tsearch.pgweb VALUES(9, 'Brazil, officially the Federative Republic of Brazil, is the largest country in both South America and Latin America.', 'Brazil', '2010-1-1'); gaussdb=# INSERT INTO tsearch.pgweb VALUES(10, 'Canada is a country in the northern half of North America.', 'Canada', '2010-1-1'); gaussdb=# INSERT INTO tsearch.pgweb VALUES(11, 'Mexico, officially the United Mexican States, is a federal republic in the southern part of North America.', 'Mexico', '2010-1-1'); gaussdb=# CREATE INDEX pgweb_idx_1 ON tsearch.pgweb USING gin(to_tsvector('english', body)); |
to_tsvector()函数有两个版本。只输入一个参数的版本和输入两个参数的版本。只输入一个参数时,系统默认采用default_text_search_config所指定的默认配置。
请注意:创建索引时请使用to_tsvector的两参数版本。只有指定了文本搜索配置的全文检索函数才可以在索引表达式中正确被使用。这是因为索引的内容必须不受default_text_search_config的影响,否则索引内容可能不一致。由于default_text_search_config的值可以随时调整,从而导致不同条目生成的tsvector采用了不同的文本搜索配置,并且没有办法区分究竟使用了哪一个文本搜索配置。正确地转储和恢复这样的索引也是不可能的。
因为在上述创建索引中to_tsvector使用了两个参数,只有当查询时也使用了两个参数,且参数值与索引中相同时,才会使用该索引。即WHERE to_tsvector('english', body) @@ 'a & b' 可以使用索引,但WHERE to_tsvector(body) @@ 'a & b'不能使用索引。这确保只使用这样的索引——索引各条目是使用相同的分词器创建的。
索引中的分词器名称由另一列指定时可以建立更复杂的表达式索引。例如:
1 2 | gaussdb=# ALTER TABLE tsearch.pgweb ADD COLUMN config_name regconfig; gaussdb=# CREATE INDEX pgweb_idx_2 ON tsearch.pgweb USING gin(to_tsvector('ngram', body)); |
这允许在同一个索引中有混合配置,同时记录具体的配置被用于每一个索引项。例如,当如果文档集合中包含不同语言的文档时,这就可能会有用。同样,要使用索引的查询也必须匹配索引表达式,例如WHERE to_tsvector(config_name, body) @@ 'a & b'。
索引甚至可以连接列:
1 | gaussdb=# CREATE INDEX pgweb_idx_3 ON tsearch.pgweb USING gin(to_tsvector('english', title || ' ' || body)); |
另一个方法是创建一个单独的tsvector列控制to_tsvector的输出。下面的例子是title和body的连接, 当其它是NULL的时候,使用coalesce确保一个字段仍然会被索引:
1 2 | gaussdb=# ALTER TABLE tsearch.pgweb ADD COLUMN textsearchable_index_col tsvector; gaussdb=# UPDATE tsearch.pgweb SET textsearchable_index_col = to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,'')); |
然后为加速搜索创建一个GIN索引:
1 | gaussdb=# CREATE INDEX textsearch_idx_4 ON tsearch.pgweb USING gin(textsearchable_index_col); |
现在就可以执行一个快速全文搜索:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | gaussdb=# SELECT title FROM tsearch.pgweb WHERE textsearchable_index_col @@ to_tsquery('north & america') ORDER BY last_mod_date DESC LIMIT 10; title -------- Canada Mexico (2 rows) -- 删除表 gaussdb=# DROP TABLE tsearch.pgweb; gaussdb=# DROP SCHEMA tsearch; |
相比于一个表达式索引,单独列方法的一个优势是:它没有必要在查询时明确指定分词器以便能使用索引。正如上面例子所示,查询可以依赖于default_text_search_config。另一个优势是搜索比较快速,因为它没有必要重新利用to_tsvector调用来验证索引匹配。表达式索引方法更容易建立,且它需要较少的磁盘空间,因为tsvector形式没有明确存储。
tsvector支持在USTORE存储引擎下创建UGIN索引。
1 2 3 4 5 6 7 8 9 | -- 创建表。 gaussdb=# CREATE TABLE ustore_tbl (id int, content text, ts tsvector) WITH (storage_type = USTORE); -- 创建索引。 gaussdb=# CREATE INDEX textsearch_ugin_idx1 ON ustore_tbl USING ugin(ts); gaussdb=# CREATE INDEX textsearch_ugin_idx2 ON ustore_tbl USING ugin(to_tsvector('english', content)); -- 删除表。 gaussdb=# DROP TABLE ustore_tbl; |
