Postgres 可以索引存储在列中的正则表达式吗?

Kri*_*ján 4 postgresql index regular-expression postgresql-9.4

我将正则表达式作为varchars存储在列中,我需要将其与传入的输入进行匹配。例如,该表可能包含:

| field |     value     |
|-------|---------------|
| email | .*@domain.com |
Run Code Online (Sandbox Code Playgroud)

查询将是:

SELECT *
FROM table
WHERE field = 'email'
  AND 'someone@domain.com' ~* value
Run Code Online (Sandbox Code Playgroud)

我将是第一个承认这很愚蠢的人,尽管它在大约 2 年中做得足够好。该表现在达到了令人震惊的 10k 行,查询速度减慢到 3 秒的数量级。我已经把我们带到了一个更合理的策略,所以这个问题纯粹是学术性的。

如果我保留了这个设置,有什么办法可以提高查找效率吗?我希望有 的一些兄弟姐妹varchar_pattern_ops,但这个查询与解决的问题相反。


有了这个想法,这里是完整的表格、查询和解释。

+------------+-----------------------------+------------------------------------------------------------+
| Column     | Type                        | Modifiers                                                  |
|------------+-----------------------------+------------------------------------------------------------|
| id         | integer                     | not null default nextval('table_id_seq'::regclass)         |
| field      | character varying(255)      | not null                                                   |
| value      | character varying(1000)     | not null                                                   |
| comment    | text                        |                                                            |
+------------+-----------------------------+------------------------------------------------------------+
Indexes:
    "table_pkey" PRIMARY KEY, btree (id)
    "index_table_on_field_and_value" UNIQUE, btree (field, value)


EXPLAIN ANALYZE
SELECT *
FROM table
WHERE (
    (field = 'contact_email' AND 'person@place.com' ~* value)
 OR (field = 'phone'         AND value = '1234567890')
 OR (field = 'unique_id'     AND value = 'abcdef')
);

Seq Scan on table (cost=0.00..613.08 rows=58 width=1) (actual time=744.371..744.371 rows=0 loops=1)
Filter: ((((field)::text = 'contact_email'::text) AND ('person@place.com'::text ~* (value)::text))
      OR (((field)::text = 'phone'::text) AND ((value)::text = '01234567890'::text))              
      OR (((field)::text = 'unique_id'::text) AND ((value)::text = 'abcdef'::text)))             
Rows Removed by Filter: 11643
Total runtime: 744.395 ms
Run Code Online (Sandbox Code Playgroud)

Cra*_*ger 6

简短版本:没有。没有实用的方法(至少在 PostgreSQL 中)来索引模式列,因此它可以与纯文本输入匹配,以加快“此纯文本是否与这些模式中的任何一个匹配”查询的速度。

PostgreSQL 需要一个“理解”模式匹配的特殊自定义索引类型。我不确定实施一个索引有多实用,也不确定从这样的索引中可以获得多少。由于没有,这个问题有点学术性。