一个关于CLR函数的性能问题,求解

yxhcool 2013-03-14 02:06:14
因为SQL Server没有时间戳函数,因此自己用CLR函数写了个,可以自动获取时区将时间转换为linux时间戳:
[Microsoft.SqlServer.Server.SqlFunction]
public static double Unix_TimeStamp(DateTime dt)
{
return Convert.ToInt32((TimeZone.CurrentTimeZone.ToUniversalTime(dt)-new DateTime(1970,1,1)).TotalSeconds);
}

但在最近使用中,发现一些语句利用这个函数后速度十分慢,比如:
SELECT ISNULL(SUM(money),0) AS money
from [tb_recharge]
where ExchangeType=0 AND
createDate>=dbo.UNIX_TIMESTAMP('2013-03-14')

createDate字段为整数类型的时间戳,并且有索引,表大小在200w左右,耗时需要20秒。

如果我将时间直接转换为数字后,耗时则不到1秒:
SELECT ISNULL(SUM(money),0) AS money
from [tb_recharge]
where ExchangeType=0 AND
createDate>=1363190400

分析执行计划,发现并不相同,虽然都利用了索引,但效率完全不同。百思不得其解,为啥SQL Server 这么傻,难道不会先把dbo.UNIX_TIMESTAMP('2013-03-14') 一次性算出来再去计算?或者是因为CLR函数的其他特殊性引起的性能下降?希望有大神帮忙解答下。
...全文
117 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
yxhcool 2013-03-14
  • 打赏
  • 举报
回复
改为DATEDIFF来实现函数后,效果也是一样的,但如果不用自定义函数速度是很快的。看来SQL Server 的查询条件不适合采用自定义函数。
yxhcool 2013-03-14
  • 打赏
  • 举报
回复
引用 1 楼 stublue 的回复:
1.lz的这个函数可以用DATEDIFF函数来实现,应该要快一些 2.可以把先dbo.UNIX_TIMESTAMP('2013-03-14')赋给一个int变量,然后createDate>=int变量,来查询
是这样的,因为我们的服务器有的在海外,时区不同,又想统一发布,而CLR里面可以进行时区判断,所以就用CLR了,看来为了性能还是得改回传统函数啊
guguda2008 2013-03-14
  • 打赏
  • 举报
回复
哼哼哼,MSSQL就是这么傻,你得把那个常量运算结题先放到变量里,再用变量当条件,不然MSSQL会每行算一遍。
Vidor 2013-03-14
  • 打赏
  • 举报
回复
程序集加载要时间吧,第2次执行呢?
szm341 2013-03-14
  • 打赏
  • 举报
回复
没怎么实践过CLR的,不过感觉应该不会太慢吧 同意ls的方法,sqlserver本身自带datadiff函数完全可以处理啊
Leon_He2014 2013-03-14
  • 打赏
  • 举报
回复
1.lz的这个函数可以用DATEDIFF函数来实现,应该要快一些 2.可以把先dbo.UNIX_TIMESTAMP('2013-03-14')赋给一个int变量,然后createDate>=int变量,来查询

22,210

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧