我正在使用 PostgreSQL,当前版本为 9.2,但我愿意升级。
在我的一个表中,有一列 text
类型的列,用于存储正则表达式模式。
CREATE TABLE foo (
id serial,
pattern text,
PRIMARY KEY(id)
);
CREATE INDEX foo_pattern_idx ON foo(pattern);
然后我像这样查询它:
INSERT INTO foo (pattern) VALUES ('^abc.*$');
SELECT * FROM foo WHERE 'abc literal string' ~ pattern;
我知道这是一种反向LIKE
或反向模式匹配。如果是另一种更常见的方式,如果我的大海捞针在数据库中,并且我的针已锚定,那么我可以根据确切的搜索模式和数据或多或少有效地使用 btree 索引。
但是我拥有的数据是一个模式表以及与模式相关的其他数据。我需要询问数据库哪些行具有与我的查询文本匹配的模式。有没有办法比检查表中每一行的顺序扫描更有效?
最佳答案
没有办法。
索引需要IMMUTABLE
表达式。表达式的结果取决于输入字符串。除了评估每一行的表达式(这意味着顺序扫描)之外,我没有看到任何其他方法。
相关答案以及 IMMUTABLE
的更多详细信息角度:
只是没有针对您的案例的解决方法,这是不可能建立索引的。索引需要在其元组中存储常量值,这是不可用的,因为每行的结果值都是根据输入计算的。并且您无法在不查看列值的情况下转换输入。
Postgres 索引的使用与运算符绑定(bind),并且只能使用运算符左侧表达式上的索引(由于相同的逻辑限制)。更多:
许多运算符定义 COMMUTATOR
它允许查询规划器/优化器将索引表达式向左翻转。简单的例子:=
的换向器是 =
。 >
的换向器是 <
反之亦然。 The documentation:
the index-scan machinery expects to see the indexed column on the left of the operator it is given.
正则表达式匹配运算符 ~
再次没有换向器,因为这是不可能的。亲自看看:
SELECT oprname, oprright::regtype, oprleft::regtype, oprcom
FROM pg_operator
WHERE oprname = '~'
AND 'text'::regtype IN (oprright, oprleft);
oprname | oprright | oprleft | oprcom
---------+----------+-----------+------------
~ | text | name | 0
~ | text | text | 0
~ | text | character | 0
~ | text | citext | 0
oprcom
... Commutator of this operator, if any
...
Unused column contain zeroes. For example,oprleft
is zero for a prefix operator.
我以前尝试过,但不得不接受它原则上不可能。
关于regex - 有没有办法有效地索引包含正则表达式模式的文本列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34504758/