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

Mic*_*cht 5 sql postgresql query-optimization sql-like

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

让我们从表开​​始:

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

CREATE INDEX path_idx ON dir(path TEXT_pattern_ops);
Run Code Online (Sandbox Code Playgroud)

插入示例数据后,我可以执行以下操作:

EXPLAIN ANALYZE 
SELECT id, path FROM dir
   WHERE path LIKE 'A%'
      OR path LIKE 'B%'
      OR path LIKE 'C%';
Run Code Online (Sandbox Code Playgroud)

以上查询正确使用索引。

第二种方式:

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

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

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

EXPLAIN ANALYZE 
SELECT id, path FROM dir
  JOIN patterns ON (dir.path LIKE patterns.pattern);
Run Code Online (Sandbox Code Playgroud)

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

这是 SQL Fiddle 对于那些想要玩这些查询的人:http : //sqlfiddle.com/#!17/24031/2

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

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

Lau*_*lbe 2

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

为此,您需要pg_trgm扩展;以超级用户身份运行以下命令:

CREATE EXTENSION pg_trgm;
Run Code Online (Sandbox Code Playgroud)

然后你可以创建一个GIN索引:

CREATE INDEX ON dir USING gin (path gin_trgm_ops);
Run Code Online (Sandbox Code Playgroud)

该索引可以与您的第二种和第三种方法一起使用,因此它应该可以满足您的需要。

对于像示例中这样的短模式,索引不会非常有效。

您还可以使用 GiST 索引,它可能更小,但搜索速度更慢。

请注意,您也可以将该索引与以 开头的模式一起使用%