非索引数据的最快SQL查询

时间:2010-11-09 22:09:44

标签: sql-server-2005 stored-procedures indexing indexed-view

我正在针对SQL Server 2005数据库构建一些自定义报告。该数据库属于我们运行的第三方管理应用程序。我提取的数据不属于网站的主要目的,因此除了时间戳列以外,数据基本上没有索引。目前,只涉及一个表 - 一个包含约7亿行的表。因此,当我针对它运行一个只返回50行的查询时,它必须轮询所有700mil。

我希望加快速度,但不想索引我添加到WHERE子句的每一列 - 我不知道添加那么多索引最终会提高速度(还是我错了?)所以我很好奇如果我无法向表中添加任何新索引,最佳做法是什么!

存储过程似乎不是最合适的。索引视图可能是最好的主意吗?想法?

这是表格架构:

DeviceGuid (PK, uniqueidentifier, not null)
DeviceID (int, not null)
WindowsEventID (PK, int, not null) (indexed)
EventLog (varchar(64), not null)
EventSource (varchar(64), not null)
EventID (int, not null)
Severity (int, not null)
Description (nvarchar(max), not null)
TimeOfEvent (PK, datetime, not null) (indexed)
OccurrenceNbr (int, not null)

以下是一个示例查询:

SELECT COUNT(*) AS NumOcc, EventID, EventLog, EventSource, Severity, TimeOfEvent, Description
FROM WindowsEvent
WHERE DeviceID='34818'
    AND Severity=1
    AND TimeOfEvent >= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/10/27 12:00:00 AM')
    AND TimeOfEvent <= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/11/3 12:00:00 AM')
    AND EventID<>34113
    AND EventID<>34114
    AND EventID<>34112
    AND EventID<>57755
    AND EventSource<>'AutoImportSvc.exe'
    AND EventLog='Application'
GROUP BY EventID, EventLog, EventSource, Severity, Description
ORDER BY NumOcc DESC

也许查询很糟糕......它在4.5分钟内返回53行。

4 个答案:

答案 0 :(得分:0)

如果你的查询没有使用任何索引,那将是非常糟糕的。您不需要每列都有索引,但是您需要在右列上使用索引。鉴于TimeOfEvent已被索引,它可能不是一个很好的满足您的需求。

右栏将取决于您的数据分布。最佳索引可能是提供最高选择性的索引(即,当您知道索引的键值时,它返回最少的行)。如果您知道提供最佳选择性的列,则可以尝试使用索引。

为了帮助确定最佳索引,您可以使用SSMS中的显示估计执行计划。这将帮助您查看将使用哪个索引。添加索引后,您可以运行查询并使用执行计划评估结果。当然,观察经过的时间也会有所帮助。

答案 1 :(得分:0)

使用双row_number技巧尝试此方法:

SELECT  RN_Desc as NumOcc, *
FROM    (
        SELECT  row_number() Over(partition by EventId order by EventLog, EventSource, Severity, Description) as RN_Asc,
                row_number() Over(partition by EventId order by EventLog desc, EventSource desc, Severity desc, Description desc) as RN_Desc,
                *
        FROM    WindowsEvent 
        WHERE   DeviceID='34818' 
                AND Severity=1 
                AND TimeOfEvent >= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/10/27 12:00:00 AM') 
                AND TimeOfEvent <= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/11/3 12:00:00 AM') 
                AND EventID<>34113 
                AND EventID<>34114 
                AND EventID<>34112 
                AND EventID<>57755 
                AND EventSource<>'AutoImportSvc.exe' 
                AND EventLog='Application' 
        ) t
WHERE   RN_Asc = 1 
ORDER BY NumOcc DESC 

有了这个引擎,只需一次通过表就不需要进行任何聚合。 如果它不起作用尝试按顺序播放并按部分rownumber分区以获得正确的分组。

答案 2 :(得分:0)

这里的最终解决方案是对索引字段运行查询,然后在运行查询的应用程序中对其进行过滤。最后两个字段包含足够相似的信息,我可以查询一个索引并获得我想要的非常接近的数据。我循环回来并从结果列表中删除任何不匹配的实体。花了很多时间!

答案 3 :(得分:0)

这很简单,但我会尝试将索引值作为

中的第一个测试
相关问题