使用内置SQL函数编译的Linq查询

时间:2010-03-30 21:04:15

标签: c# sql indexing

我有一个查询,我正在C#中执行,这花费了太多时间:

string Query = "SELECT COUNT(HISTORYID) FROM HISTORY WHERE YEAR(CREATEDATE) = YEAR(GETDATE()) ";
Query += "AND MONTH(CREATEDATE) = MONTH(GETDATE()) AND DAY(CREATEDATE) = DAY(GETDATE()) AND USERID = '" + EmployeeID + "' ";
Query += "AND TYPE = '5'";

然后我使用SqlCommand Command = new SqlCommand(Query,Connection)和SqlDataReader Reader = Command.ExecuteReader()来读入数据。这需要一分钟才能从C#执行,但在SSMS中要快得多。

我从谷歌搜索中看到你可以用CompiledQuery做一些事情,但我很困惑我是否仍然可以使用内置的SQL函数YEAR,MONTH,DAY和GETDATE。

如果有人能告诉我如何使用内置函数创建和调用编译查询的示例,我将非常感激!提前谢谢。

3 个答案:

答案 0 :(得分:3)

不幸的是,编译的查询对你没有帮助:编译时间可能不是一分钟的重要部分。我假设您已经有一个包含部分或全部(createdate, userid, type)的索引。如果没有,请添加索引。

可能的问题是您使用函数将阻止使用创建的任何索引,从而导致索引扫描或表扫描速度慢。重写您的查询以改为使用BETWEEN,它应该能够使用索引。这将使它更快。

此外,在查询中使用EXPLAIN来查看它正在使用哪些索引(如果有)。在这里发布这些信息。

答案 1 :(得分:2)

Linq to Sql不是解决查询所有性能问题的神奇工具。实际上它会产生类似的查询。而是分析您的查询以找出它的缓慢位置,并通过调整查询和/或调整索引来修复这些问题。

此外,我必须指出这样做是不好的做法:

AND USERID = '" + EmployeeID + "' "

而是尝试使用参数化查询。这意味着您使用:

AND USERID=@UserId

然后,在执行命令之前设置该参数(假设NVARCHAR(255),调整为需要):

commmand.Parameters.Add("@UserId", SqlDbType.NVarChar, 255).Value = EmployeeID;

答案 2 :(得分:2)

即使您在CREATEDATE上有索引,它也不会使用它。您需要将日期逻辑更改为GETDATE()日期时间到以下日期:

WHERE CREATEDATE>=DATEADD(day,DATEDIFF(day,0,GETDATE()),0)
   AND CREATEDATE<DATEADD(day,DATEDIFF(day,0,GETDATE()),0)+1 ...

在列上使用该函数时,例如:YEAR(CREATEDATE),可以防止使用索引。