2011-06-14 49 views
1

我認爲使用CLR觸發器而不是傳統的T-SQL觸發器是因爲我需要使用已經在C#中實現的一些邏輯。我知道SQL服務器支持CLR集成,在我看來,這似乎是一個值得一試的解決方案。CLR觸發器狀態

但是,我想要執行的操作可能有點慢。速度不夠慢,無法完全排除在觸發操作中使用它們,但插入數十萬條記錄時可能明顯緩慢。最慢的部分可以從緩存中受益很大,我猜想緩存未命中和成千上萬的緩存命中會很少。在這一點上,所有的問題都會導致一個問題:CLR觸發器可以有任何狀態嗎?而且,更重要的是,這個國家的生命週期是什麼?我想我可以使用觸發器類的靜態字段來保存某些狀態,但我不知道它何時被初始化(當服務器啓動時?在事務啓動時?未指定?)。我不確定它是否是安全的路線,因此詢問在CLR觸發器中使用某些狀態的常見做法是什麼(如果有的話)。爲了避免混淆:我需要緩存CLR對象,而不是一些SQL查詢的結果,所以它不是關於SQL Server本身在緩存方面有多好,我想緩存一些不屬於數據庫。另外,我認爲CLR並不是因爲我無法在T-SQL中進行字符串操作和綁定檢查。我需要執行一些在CLR類庫中實現的邏輯,並且有很多依賴關係。在這種情況下,我應該使用觸發器是另一個與這個觸發器幾乎沒有關係的問題。

非常感謝提前。

PS:我會欣賞任何關於主題的評論和見解,甚至那些不直接回答我的問題的人,但請不要一概而論「觸發器是邪惡的,不應該被使用「和」CLR整合緩慢且主要相容性疼痛「。另外,我知道它可能會向某人尖叫「不成熟的優化」,但此刻我只想知道我的優化選項是怎麼回事,因爲我不熟悉SQL Server中的CLR集成。我不會優化它,除非分析結果表明如此,但我不想實現整個事情來認識它太慢,我無能爲力。

我使用SQL Server 2008和.NET 3.5。

+0

緩存在內存中?這是SQL Server已經擅長的事情之一。 – 2011-06-14 09:50:31

+0

@米奇小麥:請你詳細說明一下嗎? – Dyppl 2011-06-14 09:51:52

+0

對於正確配置和配置好的SQL Server上的大多數數據庫,80%的「熱」頁面將從RAM提供,而不是文件系統(大型數據庫除外)。如果情況並非如此,你還有其他問題...(不是我的失望BTW) – 2011-06-14 09:53:59

回答

0

雖然有可能在SQLCLR觸發類的緩存值使用static類領域的,有幾件事情你需要非常謹慎:

  1. 多少數據你打算緩存?你不想佔用太多的內存,SQL Server應該用於查詢。

  2. 每個裝配所有者每個數據庫都有一個AppDomain(即裝配體上的AUTHORIZATION)。這意味着任何特定程序集中的代碼都將在所有SQL Server會話(即SPID)之間共享。如果數據只是查找數據不會根據哪個進程與靜態字段進行交互而改變,那麼這很好。但是,如果每個進程的數據不同,那麼除非將諸如當前TransactionID之類的值與進程相關聯,否則這將產生「奇怪」的行爲。

  3. 如果數據是每個進程,假設您找到一種方法來區分每個特定的SPID/SESSION,那麼您將如何清理舊數據?它將存在於內存中,直到被明確刪除或AppDomain被卸載。這對於普通查找數據來說並不是問題,因爲每種新進程都不會增加該類型的數據,所以這些查找數據意味着與所有人共享。但是每個進程的數據將不斷增加,除非被清除。

  4. 由於各種原因(內存壓力,組件的丟棄/重新創建,與組件相關的安全更改,與數據庫相關的安全更改,運行DBCC FREESYSTEMCACHE('ALL')等)可以隨時卸載AppDomains。如果一個進程依賴先前進程緩存的數據,被緩存的數據可能會在順序進程之間產生不同的結果,那麼這無法保證能夠正常工作。如果在進程之間丟棄的緩存導致的結果不過是重新加載緩存的需要,那麼它應該沒問題。

其他注意事項(但沒有持謹慎態度):

    當第一種方法稱爲在大會那裏是數據庫中沒有當前正在運行的AppDomain
  1. 的AppDomain被載入大會存在於作爲該組件授權人的用戶中。

  2. 由於上述原因之一,AppDomain將保持加載狀態,直到它們被SQL Server卸載爲止,但這些情況都不會發生。意思是,AppDomain 可以保持很長時間(即直到服務器/服務重新啓動)。

  3. 每個程序集在第一次加載其中的一個方法時被加載。

  4. 爲了使用加載事件,您可以將代碼放置在靜態類構造中。請注意,沒有SqlContext可用,因此您無法在使用進程內上下文連接(即Context Connection = true)的靜態類構造函數中創建任何SqlConnection