2012-04-19 46 views
3

我運行一個使用PostgreSQL 9.1作爲後端的配方網站。當用戶搜索食譜時,我根據用戶想要查找的內容即時創建查詢。例如,如果用戶想要查找具有在30分鐘烹調時間所有的食譜,我會生成查詢:PostgreSQL - 在所有表搜索中排除特定行集合的絕對最快方法是什麼

SELECT * From Recipes WHERE CookTime < 30; 

我現在需要「隱藏」某些配方,這意味着他們將永遠不會顯示在任何搜索中,永遠。獲得他們的唯一方法是直接瞭解URL。要做到這一點,我添加了一個新列食譜表:

ALTER TABLE Recipes ADD COLUMN Hidden boolean not null default false; 
CREATE INDEX IDX_Recipes_Hidden ON Recipes(Hidden); 

我的想法是隻是硬編碼的那句「不隱藏」到每一個WHERE子句。例如,上面的查詢現在是:

select * from recipes where not Hidden and CookTime < 30; 

我的問題:

根據查詢分析器,它將會產生一個位圖到兩個指標結合起來。請記住99%的配方將會隱藏而不是。我想知道這種技術是否是從所有查詢中排除特定配方的最佳方法。我知道絕對的最快的方法是創建一個單獨的表隱藏的食譜,但是這將是重新分解了大量的,所以我想避免這種情況。

+0

爲什麼你認爲需要大量的重新分解?您可以使用一組規則將視圖隱藏在視圖後面。這是PostgreSQL中的分區工作原理> – vyegorov 2012-04-19 06:46:33

+0

「請記住99%的配方不會隱藏」請勿索引此字段,只是時間和空間的一部分。除非你使用條件索引:WHERE hidden = true – 2012-04-19 08:06:40

+0

看來我們在這裏有相同的(種)問題:http://stackoverflow.com/a/8544893/905902。無論如何,我同意@Frank Heikens;該索引可能是沒有意義的(除非所有的數據庫都保存在內存中,並且有更多的內存可用) – wildplasser 2012-04-19 08:47:35

回答

2

您是否有任何性能問題?如果你的解決方案沒有問題,那麼把更多時間浪費在不需要改變的東西上是沒有意義的。

位圖索引適用於沒有多少不同值的情況。所以在你只有真假的情況下,這很好。

你可以創建類似於物化視圖的東西,但是這似乎要做很多工作,並且創建第二個表格可能會更容易,但如果沒有任何問題,請不要更改任何內容。

的MV在Postgres的:http://tech.jonathangardner.net/wiki/PostgreSQL/Materialized_Views

+0

是的,那會大大地矯枉過正。我想知道是否我會更好地創建多列索引,但我認爲大多數查詢最終都會執行BitmapAnd。正如你所說,如果我沒有性能問題,爲什麼要麻煩呢。這個問題的一半是爲我自己的智力發展而發佈的 - 我不是數據庫專家,但我想了解更多。 – 2012-04-19 04:30:49

+0

任意添加索引不一定會提高性能。由於分頁問題IIRC,有時使用索引可能會對查詢造成嚴重破壞,並導致性能比完整表掃描更差。 – JayC 2012-04-19 04:38:50

+1

我已決定保留當前的實現,但是在'隱藏'條件下創建索引是有條件的,因爲我將永遠不會掃描隱藏的行。如果我遇到perf問題,我會考慮分區,就像你剛纔提到的那樣。謝謝! – 2012-04-19 15:25:08

0

如果沒有性能問題就可以了。

如果我是發動機,我會使用索引與CookTime得到錶行超過30較少,而在此之後我會過濾那些隱藏= TRUE。 如果您知道如何執行此操作(僅使用cooktime索引),則可以進行測試。

但如果兩個指標快...

你的分析發現使用要確保你有收集表和索引的統計信息。 (我在Oracle上有專長,不是Postgres)

+0

是的,從我的測試到目前爲止,Postgres將使用這兩個索引並創建一個BitmapAnd。可能它沒有最新的統計信息,因爲我只是創建了索引,所以在某些情況下甚至不會觸及「隱藏」索引。 – 2012-04-19 15:18:39

1

阻止行再次出現的最快方法是......刪除它們。

但如果你想圓他們爲了某種目的,但不希望他們幾乎所有的查詢,你可以重命名錶和創造,在其設立一個新的觀點。

ALTER TABLE Recipes RENAME TO AllRecipes; 
ALTER TABLE AllRecipes ADD Hidden BOOLEAN NOT NULL DEFAULT FALSE; 
CREATE VIEW Recipes AS SELECT * FROM AllRecipes WHERE NOT Hidden; 

這是最快的,你需要多少代碼重寫(假設你有許多查詢您的應用上Recipies,並希望所有的人都排除隱藏的)條款。

但它也爲您提供簡單的選項,以使其性能也變得更快。首先,您可以在隱藏上添加索引。但是你也可以把它分成兩個子表,VisibleRecipes和HiddenRecipies。視圖食譜將精確顯示VisibleRecipies中的視圖。

但是AllRecipies表可以是一個帶有VisibleRecipes和HiddenRecipes作爲其分區的父表,也可以是一個視圖本身。

+0

+1分隔ideea。但是因爲它們是1%,所以過濾它們不會有什麼大不了的。 – 2012-04-19 06:33:27

+0

在視圖上並不確定,除非它被物化(Postgres不支持)。該視圖將顯示來自'AllRecipes'的行,其中'Hidden'爲false - 與僅在查詢時直接將該子句添加到我的查詢中有什麼不同?或者你的觀點是,如果我想要分割表格,這使我處於一個更好的位置。 – 2012-04-19 15:17:01

相關問題