【问题标题】:Is there a way to usefully index a text column containing regex patterns?有没有办法有效地索引包含正则表达式模式的文本列?
【发布时间】:2016-04-02 23:11:14
【问题描述】:

我使用的是 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 索引。

但我拥有的数据是一个模式表和与模式相关的其他数据。我需要询问数据库哪些行的模式与我的查询文本匹配。有没有办法比检查表中每一行的顺序扫描更有效?

【问题讨论】:

    标签: regex postgresql indexing pattern-matching operators


    【解决方案1】:

    没有办法

    索引需要IMMUTABLE 表达式。表达式的结果取决于输入字符串。除了评估每一行的表达式,我没有看到任何其他方法,这意味着顺序扫描。

    IMMUTABLE 角度的更多详细信息的相关答案:

    只是没有针对您的情况的解决方法,这是不可能索引。索引需要在其元组中存储常量值,这是不可用的,因为每行的结果值都是根据输入计算的。而且你不能在不查看列值的情况下转换输入。

    Postgres 索引使用绑定到运算符,并且只能使用运算符 left 表达式上的索引(由于相同的逻辑限制)。更多:

    许多运算符定义了一个COMMUTATOR,它允许查询计划器/优化器将索引表达式向左翻转。简单例子:= 的换向器是=> 的换向器是 <,反之亦然。 The documentation:

    索引扫描机器希望在给定的运算符左侧看到索引列。

    正则表达式匹配运算符 ~ 没有换向器,因为那是不可能的。自己看:

    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
    

    And consult the manual here:

    oprcom ... 此运算符的换向器,如果有的话
    ...
    未使用的列包含零。例如,对于前缀运算符,oprleft 为零。

    我之前尝试过,但不得不接受它在原则上是不可能的

    【讨论】:

    • 表达式索引需要一个不可变的表达式。但是索引并不要求它们的操作符的两边都是不可变的常量,否则你不能索引任何东西,甚至WHERE column = 'literal'。更糟糕的是,应该可以创建一个 GIN 或 GIST 索引来执行此操作,但可能没有人这样做,而且可能很难做到。
    • @Tim:但是索引 do 要求运算符的 left 操作数是不可变的。所以,不,这是不可能对主体进行索引。我添加了更多解释。
    • 我不知道左操作数要求。但是 Postgresql 允许您定义自己的运算符,我没有理由不能定义我自己的 ~ 版本(命名为别的),它可以翻转参数并使用它。这将是简单的部分,我认为困难的部分将是在这个新运算符上编写一个 GiST 索引。
    • @Tim:但是有一个非常好的理由说明为什么~ 没有换向器:这是不可能的。我已经尽力说服你了。如果我错了,我再高兴不过了。但我不是。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-17
    • 2023-03-24
    相关资源
    最近更新 更多