2012-01-28 43 views
0

我正在爲某些項目爲SQL Server創建可重用的數據訪問層。我有一個問題,找到一個合適的方式來傳遞.NET decimal作爲查詢參數。最明顯的辦法:將十進制和字符串傳遞給SqlParameter的正確方法

cmd.Parameters.AddWithValue("@P0", parameterValue); 

作品幾乎不錯。該值正確存儲在DB中,但SqlClient從實際值推斷出確切類型,因此當應用程序傳遞12345.678時,它將@P0聲明爲NUMERIC(8,3)。當完全相同的查詢與其他值一起使用時,將聲明該值的精度和小數位數。由於我還不知道的原因,從SQL Server來看,這些查詢並不相同,並且它們中的每一個在sys.dm_exec_cached_plans中都有單獨的條目。 string也有同樣的問題 - 每個長度都有一個不同的查詢計劃。

我們的一些應用程序每分鐘寫入不少記錄,每個記錄的5-10 decimal值範圍變化很​​大(某些傳感器數據,某些貨幣值)。幾乎每個INSERT都得到它自己的查詢計劃,並且在一天之後,緩存了超過100k個相同查詢計劃的版本,並且佔用了幾GB的RAM。

我的想法是將所有可能的類型合併成幾個任意選擇的類型。對於decimal,當精度低於20時,我將它設置爲20.當精度大於20時,我將它設置爲最小值,比實際精度大4(例如24,28,32,36)。縮放(最小2,然後2步)和字符串(最小128,然後2的冪)類似。這種方式似乎可以控制問題 - 我已經看到每個查詢大概有100個變體,而不是100k,而SQL Server使用內存作爲緩衝池,而不是用於一些無用的計劃。

這種方法可能出錯嗎?使用SqlClient和使用decimals加載的查詢時,是否有更好的方法可以控制查詢計劃緩存?

名單的事情我不能做:

  • 使用存儲過程 - 因爲這DAL的目的是創造了很多的DBMS(SQL服務器,MS Access中,火鳥,甲骨文此刻)抽象層。
  • 強迫我的隊友以某種方式通過每個變量的實際類型 - 因爲這將是殘酷的。
  • 垃圾這個DAL,使用普通的舊DbProviderFactory和創建參數,就像是1990年 - 因爲這DAL也處理查詢創建的SQL方言,DB結構創建等
  • 垃圾這個DAL和使用像NHibernate的「正確」的DAO - 因爲這裏沒有發明。
  • 把這個問題帶到dba.stackexchange.com - 因爲它是SqlClient的問題和我使用它的方式,而不是SQL Server本身。

回答

2

您正確地確定了此處的關鍵問題,因爲讓SQL驅動程序爲您確定參數的大小,比例和精度。您通過限制精度/尺度/參數大小來減少查詢計劃的想法也是正確的。對於字符串,可以將大小設置爲預期的最大值:當查詢將具有較大大小限制的參數字符串與較小大小的varchar s進行比較時,它應該正常工作。爲小數選取幾個精度也聽起來不錯。看看你是否可以把它降到只有一對精度/規模:這可能是可能的(它對我們的項目工作非常有效)。如果你設法做到這一點,那麼你就可以爲每個SQL查詢選擇一個查詢計劃。

+0

好點,將小數位的默認類型設置爲NUMERIC(38,8)應該照顧所有可能的情況。如果出於任何原因,某人通過了小數點後8位以上的數字,我將只更改比例並保持最大精度。現在當你說我想知道爲什麼我想出許多值的複雜想法,而不是首先爲varchar(8000)和數字(38,8 + n)。 – MagnatLU 2012-01-28 16:57:14

相關問題