我有一个 SQL 数据库和 ASP.NET Web 应用程序,我的大多数查询都涉及 SQL max 函数。
例如,下面的查询大约需要在 ASP.NET 网站和 SSMS 上执行(使用探查器时)需要 36 秒。
SELECT MAX(CONVERT(FLOAT,ISNULL(Runhrs,Runho))) -
MIN(CONVERT(FLOAT,ISNULL(Runhrs,Runho))) AS ACTUALHOURSRUN
FROM REPORTINGSYSTEM.DBO.HL_LOGS
WHERE ID_LOCATION = @ID_LOCATION AND
CONVERT(VARCHAR,TIME_STAMP,102)
BETWEEN @STARTDATE AND @ENDDATE
相关表格大约有。 5,000,000 条记录和 45 列。
执行查询以减少执行时间的最佳/最快/最有效的方法是什么?
提前致谢...
ID_LOCATION 和 TIME_STAMP 上的索引将是一个不错的选择。
但是,当您将 TIME_STAMP 字段转换为 VARCHAR 时,这将阻止它使用索引。相反,重新处理查询以消除执行 CONVERT 的需要,而是使用 DATETIME 值。
例如
SELECT MAX(CONVERT(FLOAT,ISNULL(Runhrs,Runho))) - MIN(CONVERT(FLOAT,ISNULL(Runhrs,Runho))) AS ACTUALHOURSRUN
FROM REPORTINGSYSTEM.DBO.HL_LOGS
WHERE ID_LOCATION = @ID_LOCATION AND TIME_STAMP >= @STARTDATE AND TIME_STAMP < @ENDDATE
确保@STARTDATE和@ENDDATE也是DATETIME参数(我假设这是TIME_STAMP列的数据类型)
我还想知道 Runhrs/Runho 列是什么数据类型?如果尚未存储为 FLOAT/DECIMAL,那么它们难道不是最合适的数据类型吗?
您需要做几件事:
ID_LOCATION
和 TIME_STAMP
上建立索引(如果您有其他查询按跨位置的日期或跨日期的位置进行查询,您可以考虑定义单独的索引;否则,单个组合索引将起作用)。@STARTDATE
和 @ENDDATE
的本机数据类型,或将条件替换为 TIME_STAMP between CONVERT(datetime,@STARTDATE) and CONVERT(datetime,@ENDDATE)
这两项更改应该会使您的查询更快,尤其是第二个:目前,
CONVERT(VARCHAR,TIME_STAMP,102)
强制查询优化器对与您的位置匹配的所有内容进行全面扫描,如果ID_LOCATION
上没有索引,甚至进行全表扫描。索引搜索应该将记录数量降低到可接受的水平。
最后要解决的是
CONVERT(FLOAT,ISNULL(Runhrs, Runho))
:如果前两次修改后查询速度仍然不够,请将MAX(CONVERT(FLOAT,ISNULL(Runhrs,Runho)))
更改为CONVERT(FLOAT, MAX(ISNULL(Runhrs,Runho)))
,对MIN
进行同样的更改。这可能有效,也可能无效,具体取决于 Runhrs
和 Runho
的类型。
首先,将Rhnhrs存储为数字类型。那么你就不需要进行转换了。
其次,您可以通过在
hl_logs(id_location, time_stamp)
上创建索引来加快速度。您也可以抛出 Runhrs
和 Runho
。通过对所有四列(按该顺序)建立索引,查询甚至不需要转到原始数据。
要使用索引,您需要将
where
语句更改为:
time_stamp bewteen @startTimeStamp and @EndTimeStamp
如果变量是函数的参数,SQL 引擎将不会使用索引。
生成的查询应该看起来更像:
select max(coalesce(runhrs, runho)) - min(coalesce(runhrs, runho) as Actual
from REPORTINGSYSTEM.DBO.HL_LOGS
WHERE ID_LOCATION = @ID_LOCATION AND
TIME_STAMP BETWEEN cast(@STARTDATE as datetime) AND cast(@ENDDATE as datetime)
SELECT CONVERT(FLOAT, MAX(Runhrs)), CONVERT(FLOAT, MAX(Runho),
CONVERT(FLOAT, MIN(Runhrs)), CONVERT(FLOAT, MIN(Runho)
FROM REPORTINGSYSTEM.DBO.HL_LOGS
WHERE ID_LOCATION = @ID_LOCATION
AND TIME_STAMP BETWEEN @STARTDATE AND @ENDDATE
在调用SQL的代码中自己做减法。 (这是 .net 代码。)
您应该在 ID_LOCATION、TIME_STAMP、Runhrs、Runho 上有一个索引。一个索引包含所有四个字段。也许有两个索引。
CREATE INDEX REPORTINGSYSTEM.DBO.HL_LOGS ON ID_LOCATION, TIME_STAMP, Runhrs
CREATE INDEX REPORTINGSYSTEM.DBO.HL_LOGS ON ID_LOCATION, TIME_STAMP, Runho