鉴于类似于/123/12/34/56/5/
值的字符串列,什么是查询所有记录,包括在给定数量(12
为例)的最佳方式列有效查询?上包括子
从我头顶上的解决方案是:
SELECT id FROM things WHERE things.path LIKE '%/12/%'
但据我所知这个查询可以对列,由于领先%
不使用索引。
必须有更好的东西。它是什么?
使用PostgreSQL,但宁愿该解决方案可以跨越其他数据库。
鉴于类似于/123/12/34/56/5/
值的字符串列,什么是查询所有记录,包括在给定数量(12
为例)的最佳方式列有效查询?上包括子
从我头顶上的解决方案是:
SELECT id FROM things WHERE things.path LIKE '%/12/%'
但据我所知这个查询可以对列,由于领先%
不使用索引。
必须有更好的东西。它是什么?
使用PostgreSQL,但宁愿该解决方案可以跨越其他数据库。
在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。
正常化如果你可以,但。
谢谢。这很好。尽管如此,写入性能却显着降低。 – 2012-04-16 03:58:49
RE正常化。本专栏仅用于一两个地方,不确定标准化是否值得。必须多想一想。 – 2012-04-16 04:09:36
RE规范化:规范化的形式可能会快得多。 – kgrittn 2012-04-16 09:30:20
如果你感到快乐开启该列到一个整数数组,如:
'/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)
谢谢。这是另一种选择。但是AFAIK在技术上与Erwin建议的'LIKE' + GIN索引相同,只是表达方式不同而已。 – 2012-04-16 07:03:04
这是另一个GIN索引。但它与实际数据更接近。原则上索引会更有效率,因为它不会记录包含“27 /”和“1/2”等的项目等。 – Edmund 2012-04-16 07:06:47
埃德蒙,我接受埃尔温的答案只是因为它更简单(不必更改任何代码呢)。但我希望我能接受2个答案,因为你的解决方案更加优雅。 – 2012-04-18 03:04:25
这将是最好不要有一个多值字段:) – 2012-04-16 03:49:15
我可以去与附加表“thing_paths”在它的路径。然后加入并查询它〜'从事物内部连接thing_paths中选择DISTINCT things.id on thing_path.thing_id = things.id WHERE thing.path LIKE'/ 12 /%''。但在这个阶段,它超出了我理想的状态。 – 2012-04-16 03:56:04