有效地查询包含子字符串的列

时间:2012-04-16 03:45:45

标签: sql postgresql indexing

给定一个类似于/123/12/34/56/5/的字符串列,查询包含给定数字的所有记录的最佳方式是什么(例如12) ?

我头顶的解决方案是:

SELECT id FROM things WHERE things.path LIKE '%/12/%'

但是AFAIK此查询由于前导%而无法使用列上的索引。

必须有更好的东西。它是什么?

使用PostgreSQL,但更喜欢可以在其他数据库中使用的解决方案。

2 个答案:

答案 0 :(得分:4)

如果您乐意将该列转换为整数数组,例如:

'/123/12/34/56/5/' becomes ARRAY[123,12,34,56,5]

因此path_arrINTEGER[]类型的列,然后您可以在该列上创建GIN索引:

CREATE INDEX ON things USING gin(path_arr);

对包含12的所有项目的查询将变为:

SELECT * FROM things WHERE ARRAY[12] <@ path_arr;

哪个会使用索引。在我的测试中(有一百万行),我得到的计划如下:

EXPLAIN SELECT * FROM things WHERE ARRAY[12]  <@ path_arr;
                                      QUERY PLAN
----------------------------------------------------------------------------------------
 Bitmap Heap Scan on things  (cost=5915.75..9216.99 rows=1000 width=92)
   Recheck Cond: (path_arr <@ '{12}'::integer[])
   ->  Bitmap Index Scan on things_path_arr_idx  (cost=0.00..5915.50 rows=1000 width=0)
         Index Cond: ('{12}'::integer[] <@ path_arr)
(4 rows)

答案 1 :(得分:3)

在PostgreSQL 9.1中,您可以使用pg_trgm module并使用它构建GIN索引。

CREATE EXTENSION pg_trgm; -- once per database

CREATE INDEX things_path_trgm_gin_idx ON things USING gin (path gin_trgm_ops);

即使没有左锚定,您的LIKE表达式也可以使用此索引。

查看详细的demo by depesz here

将其标准化如果你可以,那么。