给定一个值类似于 的字符串列/123/12/34/56/5/
,查询包含给定数字(12
例如)的所有记录的最佳方法是什么?
我头脑中的解决方案是:
SELECT id FROM things WHERE things.path LIKE '%/12/%'
但是 AFAIK 由于前导,此查询不能在列上使用索引%
。
一定有更好的东西。它是什么?
使用 PostgreSQL,但更喜欢适用于其他数据库的解决方案。
给定一个值类似于 的字符串列/123/12/34/56/5/
,查询包含给定数字(12
例如)的所有记录的最佳方法是什么?
我头脑中的解决方案是:
SELECT id FROM things WHERE things.path LIKE '%/12/%'
但是 AFAIK 由于前导,此查询不能在列上使用索引%
。
一定有更好的东西。它是什么?
使用 PostgreSQL,但更喜欢适用于其他数据库的解决方案。
如果您愿意将该列转换为整数数组,例如:
'/123/12/34/56/5/' becomes ARRAY[123,12,34,56,5]
这path_arr
是一个 type 的列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)
在 PostgreSQL 9.1 中,您可以使用该pg_trgm
模块并使用它构建 GIN 索引。
CREATE EXTENSION pg_trgm; -- once per database
CREATE INDEX things_path_trgm_gin_idx ON things USING gin (path gin_trgm_ops);
LIKE
即使不是左锚,您的表达式也可以使用此索引。
请在此处查看 depesz的详细演示。
但是,如果可以,请对其进行规范化。