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