【发布时间】:2012-07-17 09:35:21
【问题描述】:
我们目前有一个LOGS TABLE,由多个日志编号(XLOG 列)划分,并在有限的时间范围内访问。
该表使用集群“自然”主键声明,其中XLOG 是日志标识符,XDATE 是时间戳,XHW and XCELL 是硬件标识符,确保日志事件的唯一性:
CREATE TABLE [dbo].[LOGS](
[XDATE] [datetime] NOT NULL,
[XHW] [nvarchar](3) NOT NULL,
[XCELL] [nvarchar](3) NOT NULL,
[XALIAS] [nvarchar](255) NULL,
[XMESSAGE] [nvarchar](255) NULL,
[XLOG] [int] NOT NULL,
CONSTRAINT [PK_LOG] PRIMARY KEY CLUSTERED ([XLOG] ASC,[XDATE] ASC,[XHW] ASC,[XCELL] ASC)
问题是使用相同查询访问多个日志时会出现可怕的执行计划(例如,下面的示例查询中的XLOG = 1 OR XLOG = 1002),请求#1:
SELECT TOP 100 XDATE, XHW, XCELL, XMESSAGE, XLOG FROM LOGS
WHERE XDATE > '2012-06-12T00:00:00' AND XDATE < '2012-07-13T08:29:03.250'
AND (XLOG = 1 OR XLOG = 1002)
ORDER BY XDATE DESC, XLOG DESC
编辑:所需的 100 行不仅来自日志 #1,而且来自两个日志,混合,日期排序。这就是两个查询的返回值。
统计数据在测试前更新。
实际的执行计划基本上使用聚集索引查找来获取百万行数据,其中谓词为XLOG 和XDATE,(由于我们有 XLOG= 并且我们 TOP 顺序,它可能只获取第一/最后 100 行通过 XDATE)
聚集索引查找操作详情:
预期的执行计划是
我试图重写查询,但除了UNION ALL 之外找不到其他方法。结果查询返回相同的结果(具有正确的计划!),但感觉过于复杂(并且不能通过 XLOG 上的 JOIN 进行调整,但这不是问题)请求 #2:
WITH A AS (SELECT TOP 100 XDATE, XHW, XCELL, XMESSAGE, XLOG FROM LOGS
WHERE XDATE > '2012-06-12T00:00:00' AND XDATE < '2012-07-13T08:29:03.250'
AND XLOG = 1
ORDER BY XDATE DESC),
B AS (SELECT TOP 100 XDATE, XHW, XCELL, XMESSAGE, XLOG FROM LOGS
WHERE XDATE > '2012-06-12T00:00:00' AND XDATE < '2012-07-13T08:29:03.250'
AND XLOG = 1002
ORDER BY XDATE DESC)
SELECT TOP 100 * FROM (
SELECT * FROM A
UNION ALL
SELECT * FROM B
) A
ORDER BY XDATE DESC, XLOG DESC
问题:请求 #1 有什么问题?在尝试对数百万行进行排序之前,如何重写/修改它以考虑“TOP”?是否需要另一个索引、提示或一些额外的统计信息来解决问题?我有义务重写请求 #2 之类的查询吗?
编辑:从数量上看,这张表包含十几个日志,有些每月只有一个事件,而其他每月有数百万个事件。
这种查询最常用于此表(还有其他带有额外过滤器的变体,但它们与此问题无关——除了使用请求 #2 时的复杂性)。
编辑 #2: 我尝试了将聚集索引更改为 (XDATE,XLOG,...) 而不是 (XLOG,XDATE,...) 的解决方案 -- nb: This Composite主键是这样设计的,因为 XLOG 列的选择性低。
我在生产数据库的副本上测试了这个查询,对照只有一千行的日志:查询计划生成了很多 I/O(它只从 XLOG=12 中过滤掉几行范围广泛的XDATEs)。所以这个特殊的解决方案是不行的。
SELECT TOP 100 XDATE, XHW, XCELL, XMESSAGE, XLOG FROM LOGS
WHERE XDATE > '2012-06-12T00:00:00' AND XDATE < '2012-07-13T08:29:03.250'
AND (XLOG = 12 AND XALIAS LIKE 'KEYWORD%' )
ORDER BY XDATE DESC, XLOG DESC, XHW DESC, XCELL DESC
PS:顺便说一句,我们与 PostgreSQL 9.1 有相同的行为 - 所以它与数据库无关,更可能是错误的查询或错误的表设计。
【问题讨论】:
-
这张表上有哪些索引?
-
除了主键没有其他索引
-
索引是一个选项。这不是我为解决这个问题而探索的解决方案。
标签: sql-server sql-server-2008 sql-server-2005 postgresql sql-execution-plan