如何使用多个 LIKE 运算符并使用索引

How to use many LIKE operators and use index

在我的查询中,我想查找与许多 LIKE 运算符之一匹配的行。我知道 3 种方法,但只有一种可以使用索引。

让我们从 table 开始:

CREATE TABLE dir (
    id BIGSERIAL PRIMARY KEY,
    path TEXT NOT NULL
);

CREATE INDEX path_idx ON dir(path TEXT_pattern_ops);

插入样本数据后我可以做:

EXPLAIN ANALYZE 
SELECT id, path FROM dir
   WHERE path LIKE 'A%'
      OR path LIKE 'B%'
      OR path LIKE 'C%';

以上查询正确使用了索引。

第二种方式:

EXPLAIN ANALYZE 
SELECT id, path FROM dir
  WHERE path LIKE ANY(ARRAY['A%', 'B%', 'C%']::TEXT[]);

这个查询不会使用索引。 我知道的最后一种方法:

CREATE TABLE patterns (pattern) AS VALUES
('A%'),
('B%'),
('C%');

EXPLAIN ANALYZE 
SELECT id, path FROM dir
  JOIN patterns ON (dir.path LIKE patterns.pattern);

这个查询和上一个查询一样不会使用索引。

这里 SQL Fiddle 供那些想使用这些查询的人参考:http://sqlfiddle.com/#!17/24031/2

问题: 使用 path LIKE X OR path LIKE Y 的查询对于许多模式来说是完全不可读的(模式的数量可能从几个到几百个或几千个不等)而且恐怕很大查询的解析速度可能很慢,甚至达到 1GB 的查询长度限制(某些模式可能有很长的前缀)。

问题:是否有任何返回相同结果的其他方法不需要将所有模式直接放入查询中(就像在这个带有连接的选项中)?

您可以创建一个三元组索引来支持您的查询。

为此,您需要 pg_trgm 扩展名; 运行 以下为超级用户:

CREATE EXTENSION pg_trgm;

然后就可以创建GIN索引了:

CREATE INDEX ON dir USING gin (path gin_trgm_ops);

此索引可与您的第二种和第三种方法一起使用,因此它应该适合您。

对于像您示例中那样的短模式,索引将不会很有效。

您也可以使用 GiST 索引,它可能会更小,但搜索起来更慢。

请注意,您也可以将该索引用于以 % 开头的模式。