【发布时间】:2011-08-24 07:47:47
【问题描述】:
表定义:
CREATE TABLE [dbo].[AllErrors](
[ID] [int] IDENTITY(1,1) NOT NULL,
[DomainLogin] [nvarchar](50) NULL,
[ExceptionDate] [datetime] NULL,
[ExceptionDescr] [nvarchar](max) NULL,
[MarketName] [nvarchar](50) NULL,
[Version] [nvarchar](50) NULL,
CONSTRAINT [PK_AllErrors] PRIMARY KEY CLUSTERED ([ID] ASC)
)
-- Add an index on the date
CREATE NONCLUSTERED INDEX [IX_ExceptionDate] ON [dbo].[AllErrors] ([ExceptionDate] ASC)
我运行这个查询:
declare @yesterday datetime
select @yesterday = getdate() - 1
SELECT * INTO #yst
from AllErrors
where ExceptionDate between @yesterday and @yesterday + 1
此代码不使用我的IX_ExceptionDate(从执行计划中收集)。它对主键索引进行聚集扫描。但是,下面的代码确实使用了IX_ExceptionDate 索引:
SELECT * INTO #yst
from AllErrors
where ExceptionDate between @yesterday and @yesterday + 1
AND ExceptionDate = ExceptionDate
这是为什么?
编辑:添加了视觉执行计划。
编辑:下面的文本执行计划。
查询 1:
|--表格插入(OBJECT:([#yst]), SET:([#yst].[ID] = [Expr1006],[#yst].[DomainLogin] = [MarketStats].[dbo] .[AllErrors].[DomainLogin],[#yst].[ExceptionDate] = [MarketStats].[dbo].[AllErrors].[ExceptionDate],[#yst].[ExceptionDescr] = [MarketStats].[dbo] .[AllErrors].[ExceptionDescr],[#yst].[MarketName] = [MarketStats].[dbo].[AllErrors].[MarketName],[#yst].[Version] = [MarketStats].[dbo] .[AllErrors].[Version])) |--顶部(ROWCOUNT est 0) |--计算标量(DEFINE:([Expr1006]=setidentity([MarketStats].[dbo].[AllErrors].[ID],(-7),(0),N'#yst'))) |-- 聚集索引扫描(OBJECT:([MarketStats].[dbo].[AllErrors].[PK_AllErrors]), WHERE:([MarketStats].[dbo].[AllErrors].[ExceptionDate]>=[@yesterday ] AND [MarketStats].[dbo].[AllErrors].[ExceptionDate]
查询 2:
|--表格插入(OBJECT:([#yst]), SET:([#yst].[ID] = [Expr1006],[#yst].[DomainLogin] = [MarketStats].[dbo] .[AllErrors].[DomainLogin],[#yst].[ExceptionDate] = [MarketStats].[dbo].[AllErrors].[ExceptionDate],[#yst].[ExceptionDescr] = [MarketStats].[dbo] .[AllErrors].[ExceptionDescr],[#yst].[MarketName] = [MarketStats].[dbo].[AllErrors].[MarketName],[#yst].[Version] = [MarketStats].[dbo] .[AllErrors].[Version])) |--顶部(ROWCOUNT est 0) |--计算标量(DEFINE:([Expr1006]=setidentity([MarketStats].[dbo].[AllErrors].[ID],(-7),(0),N'#yst'))) |-- 嵌套循环(内连接,外引用:([MarketStats].[dbo].[AllErrors].[ID],[Expr1008])优化无序预取) |--Index Seek(OBJECT:([MarketStats].[dbo].[AllErrors].[IX_ExceptionDate]), SEEK:([MarketStats].[dbo].[AllErrors].[ExceptionDate] >= [@yesterday] AND [MarketStats].[dbo].[AllErrors].[ExceptionDate]
【问题讨论】:
-
可以发一下执行计划吗?
-
你能发布计划吗,我得到的几乎一样
|--Clustered Index Scan(OBJECT:([aspnetdb].[dbo].[AllErrors].[PK_AllErrors]), WHERE:([aspnetdb].[dbo].[AllErrors].[ExceptionDate]>=[@yesterday] AND [aspnetdb].[dbo].[AllErrors].[ExceptionDate]<=[@yesterday]+'1900-01-02 00:00:00.000')) -
|--Clustered Index Scan(OBJECT:([aspnetdb].[dbo].[AllErrors].[PK_AllErrors]), WHERE:([aspnetdb].[dbo].[AllErrors].[ExceptionDate]>=[@yesterday] AND [aspnetdb].[dbo].[AllErrors].[ExceptionDate]<=[@yesterday]+'1900-01-02 00:00:00.000' AND [aspnetdb].[dbo].[AllErrors].[ExceptionDate]=[aspnetdb].[dbo].[AllErrors].[ExceptionDate])) -
编译查询时不知道变量的值是什么。你可以试试
OPTION (RECOMPILE)。我认为no-opand 子句使它相信查询将更具选择性(通常它假设 10% 将在没有统计信息的情况下匹配=- 奇怪的是它没有认识到这实际上与ExceptionDate is not null虽然这已经得到BETWEEN的保证)。两个计划中的估计行数是多少? -
@Angry - 正如我上面所说,它假设 10% 用于相等谓词,因此所有加起来!它假设中间将给出
88234.8行,然后清楚地看到AND和=并假设这会将结果的大小减小到10%,而不考虑到equals 与列本身相对的事实!
标签: sql sql-server sql-server-2005 indexing