這是一個很可怕的模式;通過更改它可以實現最佳結果,以便將多個值存儲在:
所有這些都允許您使用相當簡單和穩健的SQL表達式來確定你想要什麼,並且是可轉位(通過爲子表常規B樹索引,並通過的GiST或GIN索引對於數組和hstore)可以在大型表上獲得更好的性能。
這當然是可能的,但性能會很糟糕。一種方法是使用regexp_split_to_array
將列轉換爲數組,然後使用array operators來測試重疊。
請參閱this SQLFiddle demo,它使用了擴展的測試集,因爲您不足以證明問題。
我已經顯示「任何一組出現在列」(%%
)和「全部集合出現在列」(@>
)中,因爲它不清楚您想要的問題。
設置:
CREATE TABLE test(gah text);
INSERT INTO test(gah) VALUES
('adaf**5013**dad344'),
('23**aab**yyyy'),
('zzz**402dha**vuuuda'),
('no**matches**here**lalala'),
('5013**aab**402dha'),
('402dha**aab**somethingelse**5013'),
('402dha**aab**5013');
演示:
regress=> SELECT gah FROM test
WHERE regexp_split_to_array(gah, '\*\*') && ARRAY['5013', 'aab', '402dha'];
gah
----------------------------------
adaf**5013**dad344
23**aab**yyyy
zzz**402dha**vuuuda
5013**aab**402dha
402dha**aab**somethingelse**5013
402dha**aab**5013
(6 rows)
regress=> SELECT gah FROM test
WHERE regexp_split_to_array(gah, '\*\*') @> ARRAY['5013', 'aab', '402dha'];
gah
----------------------------------
5013**aab**402dha
402dha**aab**somethingelse**5013
402dha**aab**5013
(3 rows)
令人驚訝的是,實際上你可以創建將通過利用PostgreSQL的支持表達指數的受益此查詢的索引。當然,僅僅因爲你可以做到這一點並不意味着它是一個好主意:
regress=> CREATE INDEX test_glah_resplit_gin ON test
USING GIN((regexp_split_to_array(gah, '\*\*')));
CREATE INDEX
regress=> -- Only for testing purposes, don't use in production:
regress=> SET enable_seqscan = off;
SET
regress=> explain SELECT gah FROM test WHERE regexp_split_to_array(gah, '\*\*') @> ARRAY['5013', 'aab', '402dha'];
QUERY PLAN
-----------------------------------------------------------------------------------------------
Bitmap Heap Scan on test (cost=16.00..20.02 rows=1 width=32)
Recheck Cond: (regexp_split_to_array(gah, '\*\*'::text) @> '{5013,aab,402dha}'::text[])
-> Bitmap Index Scan on test_glah_resplit_gin (cost=0.00..16.00 rows=1 width=0)
Index Cond: (regexp_split_to_array(gah, '\*\*'::text) @> '{5013,aab,402dha}'::text[])
(4 rows)
regress=> explain SELECT gah FROM test WHERE regexp_split_to_array(gah, '\*\*') && ARRAY['5013', 'aab', '402dha'];
QUERY PLAN
-----------------------------------------------------------------------------------------------
Bitmap Heap Scan on test (cost=16.00..20.02 rows=1 width=32)
Recheck Cond: (regexp_split_to_array(gah, '\*\*'::text) && '{5013,aab,402dha}'::text[])
-> Bitmap Index Scan on test_glah_resplit_gin (cost=0.00..16.00 rows=1 width=0)
Index Cond: (regexp_split_to_array(gah, '\*\*'::text) && '{5013,aab,402dha}'::text[])
(4 rows)
GIN索引是昂貴的更新,所以你會付出顯著的性能價格上insert
/update
如果你使用這種方法。普通陣列就是這樣;使用regexp_split_to_table
來動態創建它們只會讓它變得更糟。見GIN tips和the intro to GIN indexes。
例如,使用INSERT INTO test(gah) SELECT 'aaaaabbbbb'||(x::text) FROM generate_series(1,1000000) x;
插入一百萬行到我的測試表中需要22秒的GIN索引,並在丟棄它之後1.6秒。不過,這可能是一個特別糟糕的情況,因爲價值的統一性。
4.重新設計您的數據模型以不將多個值存儲在單個列中。 –
設置'A'不會出現在任何這些表達式中。你的意思是「如果一個集合中的任何**元素包含在列中的任何部分行中」不是「**每個**」如你所寫的那樣? –
@ user1751221提問時,請*回覆*要求澄清的意見。 http://meta.stackexchange.com/questions/19756/how-do-comments-work –