0

我正在为某些项目的 SQL Server 创建可重用的数据访问层。我在寻找将 .NETdecimal作为参数传递给查询的正确方法时遇到问题。最明显的方式:

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人都有自己的查询计划,一天后缓存了超过 10 万个相同查询计划的版本,占用了几 GB 的 RAM。

我要处理的想法是将所有可能的类型合并为一些任意选择的类型。对于decimal,当精度低于 20 时,我将其设置为 20。当精度大于 20 时,我将其设置为比实际精度大的可被 4 整除的最小值(例如 24、28、32、36)。音阶(最小 2,然后是 2)和弦乐(最小 128,然后是 2 的幂)也是如此。这种方式似乎可以控制问题 - 我已经看到每个查询有大约 100 个计划变体,而不是 100k,并且 SQL Server 将内存用于缓冲池,而不是用于一些无用的计划。

这种方法有什么可能出错的吗?在使用 SqlClient 和加载的查询时,是否有更好的方法来控制查询计划缓存decimals

我不能做的事情清单:

  • 使用存储过程——因为这个 DAL 的目的是为许多 DBMS(目前是 SQL Server、MS Access、Firebird、Oracle)创建抽象层。
  • 强迫我的队友以某种方式传递每个变量的实际类型——因为那太残忍了。
  • 删除这个 DAL,使用普通的旧 DbProviderFactory 并创建像 1990 年那样的参数 - 因为这个 DAL 还处理 SQL 方言的查询创建、数据库结构创建等。
  • 丢弃这个 DAL 并使用像 NHibernate 这样的“正确”DAO - 因为它不是在这里发明的。
  • 将此问题提交给 dba.stackexchange.com - 因为这是 SqlClient 和我使用它的方式的问题,而不是 SQL Server 本身的问题。
4

1 回答 1

2

您正确地确定了此处的关键问题,即让 SQL 驱动程序为您决定参数的大小、比例和精度。您通过限制参数的精度/比例/大小来减少查询计划数量的想法听起来也是正确的。对于字符串,您可以将大小设置为您期望的最大值:当您的查询将具有较大大小限制的参数字符串与varchar较小大小的 s 进行比较时,它应该可以正常工作。只为小数选择几个精度听起来也是正确的。看看你是否能把它降低到一对精度/比例:这可能是可能的(它对我们工作中的项目非常有效)。如果您设法做到这一点,您将能够为每个 SQL 查询执行一个查询计划。

于 2012-01-28T16:47:43.610 回答