我们在 ETL 过程中使用 CLR 函数来集中处理特定的数据转换和数据检查逻辑。这些功能相当基本,不需要数据访问,并且是确定性的,因此允许并行。
例如:
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, SystemDataAccess = SystemDataAccessKind.None, IsPrecise = true)]
public static bool check_smallint(string input)
{
string teststring;
try
{
teststring = input.Trim(' ').Replace('-', '0');
if (teststring.Length == 0)
{
teststring = "0";
}
Convert.ToInt16(teststring);
}
catch (NullReferenceException)
{
return true;
}
catch (FormatException)
{
return false;
}
catch (OverflowException)
{
return false;
}
return true;
}
除了性能之外,这工作正常。查询速度大大降低,这在处理大型数据集(数百万行或更多)时造成了麻烦。
到目前为止,我们还没有发现真正了解 SQL CLR 体系结构的人,但我们收到的一个建议是,这可能是由创建新连接或为每个函数调用分配内存的开销引起的。所以一个解决方案可能是连接/内存池。
请不要提出不同的解决方案,我们已经在考虑它们,例如内联 sql,或完全不同的方法。标准的 sql 函数在许多情况下是没有选择的,因为缺乏错误引发。
附言。我们正在使用 SQL 2008R2。
最佳答案
by the overhead of creating a new connection or allocating memory for every function-call. So a solution could be connection / memory pooling.
这不是您在 C# 方面需要担心的事情。您不是在分配内存(当然,您是在分配字符串和函数内部所需的东西,没有任何东西可以汇集/重用)。此外,您不必担心连接问题。
This works fine except for performance.
您的代码正在做一些令人难以置信的事情...异常...缓慢:抛出异常而不是执行检查。 异常是一种扩展操作,应该用于处理异常情况(只有 100/200 条记录具有 null
- 或无效 - 值,它会减慢查询速度超过 1,000,000 条记录)。错误的输入格式或数据库列中的 null
值......并不是异常(exception)(这种编程风格 - 异常(exception)而不是检查 - 允许并且甚至在其他语言中受到鼓励,例如Python。我通常会在 C# 中避免使用它。可以肯定的是,在性能有问题的情况下它不合适。
public static bool check_smallint(string input)
{
if (String.IsNullOrWhiteSpace(input))
return true;
short value;
return Int16.TryParse(input, out value);
}
请注意:String.IsNullOrWhiteSpace(input)
将为 null
输入或仅由空格组成的字符串返回 true
(替换您的 Trim()
和 NullReferenceException
东西)。其他一切(FormatException
对于不是整数的输入文本或带有 OverflowException
的太大数字)由 Int16.TryParse()
处理。对于有效输入,代码更短(并且稍微快),但对于无效输入,它快很多倍。
关于c# - CLR sql server 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26340521/