我正在为某些项目创建可重用的SQL Server数据访问层。我有一个问题,找到一个正确的方法来传递.NET decimal
作为查询参数。最明显的方式:
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
加载的查询时,是否有更好的方法可以控制查询计划缓存?
我不能做的事情清单:
答案 0 :(得分:2)
您在此处正确识别了关键问题,即让SQL驱动程序为您决定参数的大小,比例和精度。您通过限制参数的精度/比例/大小来减少查询计划数量的想法听起来也是正确的。对于字符串,您可以将大小设置为您期望的最大值:当您的查询将具有较大大小限制的参数字符串与较小大小的varchar
进行比较时,它应该可以正常工作。选择几个小数精度也听起来不错。看看你是否可以将它降低到只有一对精度/比例:它可能(它对我们的工作项目非常有效)。如果您设法这样做,您将能够根据SQL查询转到单个查询计划。