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

标签 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);

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

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 扩展;以 super 用户身份运行以下命令:

CREATE EXTENSION pg_trgm;

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

CREATE INDEX ON dir USING gin (path gin_trgm_ops);

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

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

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

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

关于sql - 如何使用多个 LIKE 运算符并使用索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50176240/

相关文章:

sql - 使用子选择来完成LEFT JOIN

sql - 在 DELETE 中使用 INNER JOIN

mysql - 使用 SQL 中的数学进行级联更新

mysql - 使用依赖子查询优化 MySQL 查询

mysql - 如何优化这个依赖日期值的 JOIN 查询?

sql - 加速这个大 JOIN

sql - 创建一个基于将范围转换为行的 sql View

postgresql - Multi-Tenancy 与单租户?

sql - 如何从具有不同条件的相同数据的联合中获得单个结果

database - PostgreSQL 准备好的语句是否按语句名称缓存?