2013-10-24 46 views
1

我有一大組非規範化的數據與不均勻的屬性(有些屬性在那裏,有些不是),並將其插入到一個列。此列包含大約300個鍵/值對,每行總大小爲5000個字符。我想用ilikeOR運算符對這些屬性的某些屬性進行字符串搜索查詢,總共100000行。PostgreSQL hstore:通過索引改進LIKE性能?

查詢:

SELECT hstore->'a' AS a, hstore->'b' AS b,hstore->'c' AS c 
    FROM table 
    WHERE 
     hstore->'x' ILIKE '123%' 
    or hstore->'y' ILIKE '123%' 
    or hstore->'z' ILIKE '123%' 

隨着對沒有索引的表,我得到了> 500ms的運行時間(explain analyze)這個查詢。

使用我的舊的RDBMS索引表,其中每個屬性都在一個列中,我獲得了更好的性能,但靈活性較差。

我嘗試不同/多個索引上的那些hstore屬性,像

CREATE INDEX idx_table_hstore ON table((hstore->'a')) 

和一個索引每個,但性能是相同的不具有索引在所有。

就我所知,GIN/GIST索引不會有多大意義,因爲列很大,不需要幾何操作符(我可能在這個問題上是錯的)。

在這種情況下,您會使用哪種索引方法來獲得與使用經典模型相似甚至更好的性能?

回答

3

這很大程度上取決於您的具體使用情況,這並不完全清楚。在示例查詢中,您正在測試鍵x,y和z的值。如果這三個鍵(或者所有鍵的相對較小的子集)是唯一用於查找的鍵,那麼您可以考慮將它們移動到它們自己的列 - 那麼您的查找字段是固定的,但您仍然具有hstore列的靈活性。

也不清楚你是否在每個單獨的鍵或只是查找列創建索引。如果你在每個關鍵詞上做了一個關於300個索引(你提到有大約300個關鍵字)的關鍵字,那麼你也放棄了hstore的一些靈活性(通過創建這些索引之一爲每一個單一的關鍵)。我會堅持,只是查找列(X,Y,Z)在這裏和調整它們有點像這樣:

create index idx_t_h_x on t ((lower(h->'x'))); 

你提到的不支持ILIKE操作的指數,所以你需要指數下(或上)的值然後修改謂詞相匹配,像這樣:

SELECT hstore->'a' AS a, hstore->'b' AS b,hstore->'c' AS c 
FROM table 
WHERE lower(hstore->'x') LIKE '123%' 

此外,杜松子酒/要旨索引不僅對於幾何操作(實際上「G」在這兩個名稱都是「廣義的」 - 它們旨在用於多用途)。如果您查看the docs for the hstore module,您會看到hstore列*上的gist或gin索引支持哪些運算符。其中之一是「?」,它測試是否存在密鑰。根據查找鍵(x,y,z)的稀疏性,通過在列上定義一個gist或gin索引並添加一個額外的條件,如「where(hstore?'x'and hstore->' x'ilike'123%')「;假設沒有多少行有鍵x這應該給你一個體面的提升,否則如果鍵x幾乎在每一行,你會回到全表掃描。

當談到決定是否使用gist或杜松子酒時,如果您檢查postgres文檔並在此處查找,您會發現一些準則,基本上杜松子酒的查找速度會更快,但需要更多空間並且速度更慢建立和維護(意思是記住你是在寫更多的數據還是讀數據) - 我不確定是否有針對hstore類型的特定建議。

噢,很明顯,這一切都假設您的服務器配置適合您的硬件和使用情況。正如我指出的那樣,您提供的索引不支持ilike運算符,因此永遠不會使用。一旦獲得了您認爲應該使用的索引,您可以嘗試禁用表掃描(檢查enable_seqscan的配置)以查看是否可以確定規劃人員不使用它的原因。如果您的配置開箱即用,您可能會將random_page_cost設置爲高,如果您的work_mem不夠高,則可能會在磁盤分類上做很多操作等等。

*僅指出一個主題,並非全部索引類型支持所有運營商。