给定一个类似于/123/12/34/56/5/
的字符串列,查询包含给定数字的所有记录的最佳方式是什么(例如12
) ?
我头顶的解决方案是:
SELECT id FROM things WHERE things.path LIKE '%/12/%'
但是AFAIK此查询由于前导%
而无法使用列上的索引。
必须有更好的东西。它是什么?
使用PostgreSQL,但更喜欢可以在其他数据库中使用的解决方案。
答案 0 :(得分:4)
如果您乐意将该列转换为整数数组,例如:
'/123/12/34/56/5/' becomes ARRAY[123,12,34,56,5]
因此path_arr
是INTEGER[]
类型的列,然后您可以在该列上创建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。
将其标准化如果你可以,那么。