鑑於類似於/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