【发布时间】:2018-10-12 11:51:19
【问题描述】:
在我的查询中,我想找到与许多 LIKE 运算符之一匹配的行。我知道 3 种方法,但只有其中一种可以使用 index.html。
让我们从表格开始:
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 的查询长度限制(某些模式可能有很长的前缀)。
问题: 是否有任何 oder 方法返回相同的结果,不需要将所有模式直接放入查询中(例如在这个带有连接的选项中)?
【问题讨论】:
-
我使用的是 Postgres 9.6,但如果需要可以升级。
-
关于前缀,请问您遇到的业务问题需要这么长的前缀吗?例如,如果一个前缀是 1000 个字符,那为什么不能只是 500 个字符,让它做同样的事情呢?
-
在我原来的问题目录表中包含文件系统上目录的路径。通过此查询,我想查找所有子目录,但仅针对某些满足给定条件的目录。所以我现在要做的是创建查询以从数据库中获取这些目录,使用 SqlAlchemy 创建 SQL:为每个创建的目录创建路径 LIKE X。这对我来说似乎是不必要的步骤,唯一阻止我改变的是所有其他方法都不使用索引。
-
我会研究 ltree。将路径“转换”到 ltree 需要额外的努力,但您将拥有舒适的运算符和索引支持
-
不幸的是 ltree 的字符集非常有限。在我的情况下,路径列可以包含任何 UTF-8 字符。
标签: sql postgresql query-optimization sql-like