2010-01-26 21 views
16

我已經在SQL server中使用CLR存儲過程一段時間了,但我仍然想知道使用它們的最佳狀態是什麼。使用CLR存儲過程需要解決哪些問題?

MSDN爲重用字符串操作(regex)提供了一些使用指南,或者替換聲明大量表變量和遊標的T-SQL。我很想知道用戶使用CLR存儲特效解決什麼問題,以及示例/基準。

例如,我發現CLR存儲過程+ SSRS是一種很好的方式,可以將數據操作邏輯從SSRS和T-SQL中取出,並轉換爲易於閱讀和操作的託管代碼。

回答

23

要求非規範化和/或連續操作的許多問題都可以由CLR處理非常好,可以用來顯着提高性能,而無需在SQL結束犧牲可用性(許多)。與其完全依賴基於集合的操作或迭代操作,您可以採用混合方法,對大規模運輸使用基於集合的解決方案,並轉換爲緊密循環的迭代模型。

SQL Server 2008中內置的hierarchyid和地理空間(即geography)類型是非規範化問題的很好例子。兩者都包含(幾乎)任意大量的數據,在不損害性能的情況下很難正常化 - 您需要使用遞歸或遊標來完成任何有意義的工作,或者使用鼠標套件的觸發器和/或計劃任務來維護一個非規範化表。

我用CLR類型解決的另一個問題是內聯壓縮。這可能聽起來像是毫無意義的或學術性的練習,但是當您的完全標準化的數據推入太字節時,大小減少80-90%意味着很多。 SQL現在具有自己的內置壓縮功能,而SQL 2005具有vardecimal,並且這些工具也是很好的工具,但是在CPU負載和壓縮率方面,域感知「最小化」算法的效率要高出幾倍。顯然這不適用於所有問題,但它適用於一些問題。

在這個網站上經常發現的另一個非常常見的問題是在運行中生成一個序列 - 例如一個連續的日期序列。常見的解決方案是遞歸CTE,靜態序列表和鮮爲人知的spt_values表,但簡單的CLR UDF比其中任何一個表現都更好,並且提供了更大的靈活性。

最後在我的列表中:用戶定義的流式聚合也非常有用,尤其是與統計相關的任何事情。有些東西你根本無法從內置的SQL聚合中編寫出來,比如中值,加權移動平均數等等.UAD也可以使用多個參數,以便對它們進行參數化;從技術上講,彙總不能保證在當前版本的SQL Server中以任何特定順序接收數據,但是您可以通過給它一個ROW_NUMBER作爲附加參數來避開該限制,並使用它來實現任何窗口函數(具有總體吐出一個UDT,然後可以轉換爲一張表)。

實際上很令人沮喪的是,很少有真正有用的SQL-CLR應用程序的例子;在Google上搜索,你會得到1000萬個結果,每一個結果都是一些愚蠢的字符串連接或正則表達式。這些是有用的,但花幾分鐘時間來了解SQL UDT和UDA,特別是您將會在自己的應用程序中看到它們的大量用途。當然,不要瘋狂 - 仔細想想純SQL中是否有更好的解決方案 - 但不要打折它們。

+2

這是我讀過的最豐富的帖子之一。謝謝。 – 2010-01-27 19:56:58

+0

+1非常好地放在 – 2010-01-28 08:52:44

5

字符串操作 - 正則表達式搜索是一個經典。在CLR中很容易暴露,在直接的T-SQL中很難做到。

查看this link瞭解實施細節和微基準(SQLCLR is only 47 milliseconds compared to 6.187 seconds for the T-SQL UDF)。

5

字符串操作(正則表達式)已經被提及,但也包括DateTime算術,當然還有另一個biggie - 調用外部Web服務。

+0

嘿馬克,你可以舉一個例子,你可以通過訪問CLR過程中的外部web服務來解決這個問題嗎? +1確實有用。 – 2010-01-26 17:59:22

+0

很多東西 - 例如獲取最新的貨幣匯率,獲取最新的股票信息和更多 – 2010-01-26 18:09:02

2
  • 自定義彙總
  • 字符串操作
  • 自定義數據類型

說實話,我只看到字符串處理,其中包括分割的CSV成行。

我會考慮任何需要更多的默認信任級別超出界限,除非我是DBA做DBA類型的東西。

從MSDN用正則表達式和RSS的例子:Using CLR Integration in SQL Server 2005

3

下面是我用CLR特效的,我認爲是整齊的東西一個例子:使用CLR存儲的特效和SQL作業外部web服務

定時的數據更新。

我們有一個應用程序,可以將一些跟蹤的數據與外部行業數據提要進行同步。同步每週運行一次,並按需更新單一更新,所以我有一個現有的webservice API來訪問它。事情已經由Windows服務安排,但我想爲什麼不能像我們其他的SQL工作一樣安排它們?

我創建了一個CLR存儲過程,它提供了應用程序的webservice API。然後,我爲@RecordID添加了一些參數以支持單個同步,並在企業管理器SQL作業中安排它。

現在我可以使用作業運行dB同步或使用其他SQL proc或觸發器內的proc來更新外部提要中的數據。

未來將應用程序Web服務API取出可能會更清潔,並且只需直接使用外部Web服務即可。但現在,這是非常快速的實現方式,也是一種將功能擴展到SQL組的好方法。

1

將數據從不提供傳統SQL接口的系統中提取出來或者該接口的供應商的實現是低於標準時非常有用。

我們有一個核心應用程序構建在舊MUMPS平臺上,運行在Intersystems緩存數據庫上。數據是分層的,本質上不是關係數據。主全局數組(即表)具有多個數據級別和元素,所有數據級別和元素都按帳號分組在一起。即使掃描一列,也需要從磁盤加載整個全局,並且需要8個小時以上。供應商確實提供了ODBC驅動程序和映射到全局變量,但它經常導致掃描和極慢的查詢。

我構建了一個表值函數,它採用ObjectScript(Intersystem的MUMPS方言)程序,在Cache服務器上執行它,並將輸出行作爲數據行返回。我可以通過提供一個特定的程序在該端執行,然後在MSSQL中輕鬆地將數據作爲臨時的內聯數據源導入,從而對MUMPS端的數據訪問路徑進行微操作(這實際上是獲得高效數據訪問所需的路徑)。

我可以使用TVF驅動數據選擇或使用CROSS APPLY在另一端進行查找並且效率相當高。如果我強制MSSQL使用並行執行計劃,我甚至可以在遠程端並行運行多個查詢。

+0

>「並將輸出行作爲數據行返回。」你是否首先將數據放入System.Data.DataTable中?我有一些幫助函數來編寫數據表,但不知道如何用IEnumerable來完成。 – tbone 2015-05-28 04:33:05

+0

有一個帶有流式表值函數的FillRow方法,它具有固定的行投影。在原始版本中,我從查詢返回最多8個字符字段,如F1,F2,F3 ... – 2015-06-01 14:13:27

+0

感謝 - 相關示例我認爲:http://stackoverflow.com/questions/6901811/sql-clr-streaming-表值函數結果 – tbone 2015-06-02 17:20:37