我试图理解为什么执行一个简单的查询需要这么长时间。 在我的本地机器上需要10秒钟,但在生产中需要1分钟。 (我将数据库从生产导入我的本地数据库)
select *
from JobHistory
where dbo.LikeInList(InstanceID, 'E218553D-AAD1-47A8-931C-87B52E98A494') = 1
表DataHistory
未编入索引,且有217,302行
public partial class UserDefinedFunctions
{
[SqlFunction]
public static bool LikeInList([SqlFacet(MaxSize = -1)]SqlString value, [SqlFacet(MaxSize = -1)]SqlString list)
{
foreach (string val in list.Value.Split(new char[] { ',' }, StringSplitOptions.None))
{
Regex re = new Regex("^.*" + val.Trim() + ".*$", RegexOptions.IgnoreCase);
if (re.IsMatch(value.Value))
{
return(true);
}
}
return (false);
}
};
问题是,如果一个表有217k行,那么我将调用该函数217,000次!不知道如何重写这件事。
谢谢
答案 0 :(得分:1)
此代码存在以下几个问题:
(IsDeterministic = true, IsPrecise = true)
属性中缺少[SqlFunction]
。这样做(主要只是IsDeterministic = true
部分)将允许SQLCLR UDF参与并行执行计划。如果不设置IsDeterministic = true
,此函数将阻止并行计划,就像T-SQL UDF一样。bool
,而不是SqlBoolean
Regex.IsMatch
而不是 RegEx模式非常效率低下:将搜索字符串包装在“^。*”和“。* $”中将需要RegEx引擎解析和对于value
的每次迭代,在内存中保留为“匹配”,即foreach
输入参数的全部内容。然而,正则表达式的行为使得仅使用val.Trim()
作为整个模式将产生完全相同的结果
(可选)如果 输入参数都不会超过4000个字符,则指定MaxSize
4000
代替-1
,因为{将数据传入和传出SQLCLR对象比NVARCHAR(4000)
快得多。