2016-06-24 33 views
8

我在當前項目中使用了由oracle數據庫和memcached支持的Rails。寫密集型功能的體系結構

有一個相當沉重的使用的功能,這依賴於單個數據庫視圖用作數據源,並且該數據源在內部具有內其它數據庫視圖和表。

這是一個虛擬數據庫視圖,能夠從一個地方訪問所有內容,而不是物化數據庫視圖。

用戶大多數時候如果他們正在尋找更新的功能,那麼讓數據保持最新是非常重要的。

當從這一觀點獲得數據,我內連接安全表視圖(安全表不是視圖本身的一部分),它包含了我們用來控制上更細化的級別的數據訪問某些字段。例如,安全表具有user_id, prop_1, prop_2列,其中prop_1, prop_2是數據庫視圖上可用的列,user_id是登錄用戶。有些用戶在安全表中有相同的道具說prop_1 = 1 and prop_2 = 1,但也可以有prop_1像其他用戶,但有不同prop_2prop_1 = 2 and prop_2 = 1。 prop_1和prop_2有很多不同的組合,把它們想象成一個FK到另一個表格,這樣可能有很多條目。

現在,檢索應用程序中的記錄的時間差不多是10秒,這很慢。我正在考慮替代方法。

第一件事,我雖然是物化視圖,但由於用戶做頻繁的更新,它可能不是最好的選擇,因爲刷新視圖可能需要一段時間。

我想過的第二件事是緩存,使用prop_1prop_2組合作爲底層數據的組合鍵,因爲許多用戶具有相同的組合,並且具有相同組合的人可以訪問相同的數據。

但是這種方法可能需要更多的代碼重寫和邏輯在片段中從一個位置使用一個查詢保存和檢索數據,而不是像在數據庫視圖。

在你的經驗,你是怎麼處理相同/相似的問題?還是有更好的方法可以嘗試?

對於你們想要問的那些人,你們嘗試了些什麼。我首先想到解決方案,從可靠的資源和更有經驗的人那裏收集信息,然後我會做出明智的決定並開始實施。實施第一,思考第二,事實證明這麼多次是錯誤的

+1

您的問題似乎暗示加入安全表是導致性能下降的原因。沒有那個連接,需要多少時間來檢索相似的記錄? –

回答

0

很多次加入到複雜的視圖呈現性能問題。

prop_1,並要限制prop_2值?也就是說,您是否加入了您對這些列上的安全表的看法,如

WHERE my_view.prop_1 = security_table.prop_1 
AND my_view.prop_2 = security_table.prop_2 
AND security_table.user_id = :current_user_id 

下一個問題:做prop_1prop_2映射到視圖的基礎表中的列?如果是這樣,他們是否可以用來從基礎表快速訪問行(視圖外)?

如果是的話,我會嘗試使用DBMS_RLS.ADD_POLICY在基礎表上添加安全策略以實施安全(即,基於當前用戶的prop_1prop_2極限值),並沒有加入安全表視圖的。

如果您將安全策略添加到基礎表中,Oracle將在訪問表時添加這些謂詞,之前查詢的複雜度開始。這可能會使Oracle的優化器獲得額外的幫助,從而使該過程更快。

沒有看到你的代碼,很難說更多。

1

如果沒有關於您的觀點的更多信息,很難給出一個好的答案,但我會試一試。

首先我質疑使用一個非常複雜的視圖。這很難調整,並且經常會導致性能問題,所以如果可以將它分解到應用程序中,那將是我的第一個賭注。

其次,您是否看過包含安全過濾器的查詢的執行計劃(解釋計劃)?它是否使用合理的索引?如果沒有,創建它們。例如,安全屬性可能沒有編入索引?

第三個選項可能是使用PL/SQL並調用一個像視圖一樣的存儲過程。這使您可以更好地控制數據庫,從而可以控制查詢並將其分成多個步驟,但要獲得與Today類似的結果。

最後,您可能可以重寫視圖以獲得更好的性能。一個經常被忽略的特性是WITH子句,它可以在主查詢之前運行查詢並將結果用作表。它幫助我大幅提高了複雜視圖的性能。

DBMS_RLS很酷,但可能很貴,它需要企業版,如果您還需要單獨的許可證,它也不會讓我感到意外。我會首先尋找一個編程解決方案。 「

0

」依賴單個數據庫視圖作爲數據源,並且此數據源內部具有其他數據庫視圖和表格。「

如果這是一個對象,我們稱之爲a God Object,這是一件壞事。它與數據庫領域中的反模式一樣多。在不知道細節的情況下,很難確定,但可能會遇到內部連接,外部連接和交叉連接的混亂,導致反規範化,數據重複和(可能)完整性問題。

當然,你有性能問題,這是不可避免的,因爲這樣的事情是不可調的。無論你想要一行還是一萬行,它都是同一個查詢。你沒有給優化器做出明智決定的機會。

因此,您需要做的第一件事是將此視圖分解爲映射到重點業務域的有意義的數據對象(視圖或表)。您已經在使用Rails,管理更好的數據訪問層應該不那麼困難。

至於安全性,Oracle確實有一個內置的虛擬專用數據庫實現。如果你有企業版,你應該使用DBMS_RLS來控制行級(和列級)的訪問。RLS的主要優勢在於它不可見:在表或視圖上設置策略,並自動將其應用於在對象上執行的所有SQL。

如果你使用的是標準版,那麼你就堅持使用顯式連接到你的安全表(見下面)。

至於使用memcached,根據我的經驗,應用程序開發人員傾向於構建外部緩存,因爲他們不瞭解Oracle數據庫如何工作,因此實施不良的數據訪問策略 - 例如通過單個怪異視圖來路由所有內容。 。

將DAL分解爲離散的有意義的對象將爲您提供更好的性能,因爲數據庫優化程序將能夠選擇最有效的路徑來提取所需的精確信息集。此外,檢索路徑會更好,因爲熱點(最常被查詢的)塊將在數據庫緩衝區緩存中提供幫助,而此時我懷疑這是由於全表掃描過度而被完全拋棄。您可以利用服務器結果緩存,這可能有助於「用戶具有相同的組合並且[誰]可以訪問相同的數據」Find out more

因此,您可能發現根本不需要外部緩存。當然,通過讓數據庫正確地管理數據 - 使用適當的技術 - 你會發現你需要的外部數據少得多。您將您的應用程序描述爲「密集寫入」,因此您必須花費大量週期來保持緩存和數據庫同步。很明顯,如果你正在處理Facebook數據量,你需要使用Facebook風格的方法來進行數據管理。但一般來說,Do The Simplest Thing That Could Possibly Work仍然是最好的起點。

1

如果您經歷的一些延遲可能會導致您的數據庫,您可能會將您的某些視圖遷移到REDIS database(內存數據結構存儲),這可能是「讀/寫」密集型中最有效的一種。

關於此更新有問題,您可以實施websocket將精確更新直接推送給需要它的人。

我強調這種可能性需要對服務器端的兩個客戶端進行一些修改,但我認爲這是保持用低延遲更新最終用戶視圖的最佳方法。

致以問候