Sql server 2005 非索引数据的最快SQL查询

Sql server 2005 非索引数据的最快SQL查询,sql-server-2005,stored-procedures,indexing,indexed-view,Sql Server 2005,Stored Procedures,Indexing,Indexed View,我正在针对SQLServer2005数据库构建一些自定义报告。该数据库属于我们运行的第三方管理应用程序。我提取的数据不属于站点的主要用途,因此除了timestamp列之外,数据基本上没有索引。目前,只涉及一个表——一个约7亿行的表。因此,当我对它运行一个只返回50行的查询时,它必须轮询所有700mil行 我希望加快速度,但不想索引我添加到WHERE子句中的每一列-我不知道添加这么多索引最终会大大提高速度,还是我错了?。所以我很好奇,如果我不能向表中添加任何新索引,那么最好的做法是什么 存储过程似

我正在针对SQLServer2005数据库构建一些自定义报告。该数据库属于我们运行的第三方管理应用程序。我提取的数据不属于站点的主要用途,因此除了timestamp列之外,数据基本上没有索引。目前,只涉及一个表——一个约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行。

如果您的查询不使用任何索引,它将非常糟糕。您不需要在每一列上都有索引,但您需要在右边的列上有一个索引。鉴于TimeOfEvent已经编制了索引,它可能不适合您的需要

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


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

使用双列数字技巧尝试这种方法:

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 
有了它,引擎不需要进行任何聚合,只需对表进行一次遍历。
如果不起作用,请尝试按部分行号使用order by和partition by来获得正确的分组。

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

这是非常简单的,但我会尝试索引值,作为

中的第一个测试,您的查询数据是否需要始终保持最新,或者是否可以处理数据的快照?您可以尝试创建一个子作业,每晚解析所有数据,并将其写入已过滤/聚合数据的报表结构,以便减少需要查询的行数。如果需要的话,该表也可以有所需的索引。@Knubo-这是我们正在考虑的事情。我们通常会查看前几周的数据,因此我们可以每周将其归档到另一个数据库中。7亿行,即每行100字节,意味着需要对70GB的数据进行线性搜索。从中抽出4.5分钟真是太好了。虽然我猜数据库被锁定了,其他的什么都没有通过。取决于你正在寻找什么样的搜索,你可以考虑使用Luxin或其他索引软件来索引你的数据。我以前的一些同事在一些复杂的mysql数据库上成功地做到了这一点。我同意添加索引会有所帮助,但如果我不能添加索引会怎么样呢。有什么办法可以提高速度吗?啊,我误解了。我认为索引是一种选择。听起来@Knubo的讨论主题将是最有希望的。它节省了大约一分钟,并显著减少了行数,但仍然不够快,无法满足我们的需要。我认为建立一个单独的数据库并将数据导出到其中就是答案。