我有一个带有多个表的SQL Server 2005数据库。其中一个表用于存储多个设备的时间戳和消息计数器,并具有以下列:
CREATE TABLE [dbo].[Timestamps] ( [Id] [uniqueidentifier] NOT NULL, [MessageCounter] [bigint] NULL, [TimeReceived] [bigint] NULL, [DeviceTime] [bigint] NULL, [DeviceId] [int] NULL )
Id是唯一的主键(Guid.Comb),并且在DeviceId和MessageCounter列上都有索引。
Id
DeviceId
MessageCounter
我想做的是找到MessageCounter特定设备的最后插入的行(具有最大的行)。
奇怪的是,对 设备号 的查询 。 4 (以及除No.1以外的所有其他设备)几乎立即返回:
select top 1 * from "Timestamps" where DeviceId = 4 order by MessageCounter desc
但对 设备号的 查询相同 1 永远需要完成:
select top 1 * from "Timestamps" where DeviceId = 1 /* this is the only line changed */ order by MessageCounter desc
最奇怪的是,设备1的 行 比设备4的 行少 得多:
select count(*) from "Timestamps" where DeviceId = 4 (returns 1,839,210) select count(*) from "Timestamps" where DeviceId = 1 (returns 323,276).
有人知道我可能做错了什么吗?
[编辑]
从这两个查询的执行计划中,可以清楚地看到,设备1(下图)在索引扫描中创建了大量行:
设备4(上部)和设备1(下部)的执行计划http://img295.imageshack.us/img295/5784/execplans.png
区别在于,当我将索引扫描节点悬停在执行计划图上时:
Device 4 Actual Number of Rows: 1 Device 1 Actual Number of Rows: approx. 6,500,000
6,500,000行是一个非常奇怪的数字,因为我的select count(*)查询为设备1返回了大约300,000行!
select count(*)
尝试在上创建索引(DeviceId, MessageCounter DESC)。
(DeviceId, MessageCounter DESC)
另外,请尝试以下查询:
select * from "Timestamps" where DeviceId = 1 and MessageCounter = (SELECT MAX(MessageCounter) FROM "Timestamps" WHERE DeviceID = 1)
只是猜测:性能差异可能是因为DeviceId = 1分布在比的更多页面上DeviceId = 4。通过排序,我怀疑您正在疏通所有匹配的页面,即使最终只选择了第一行也是如此。
DeviceId = 1
DeviceId = 4