第一个查询适用于索引搜索(https://www.brentozar.com/pastetheplan/?id=B1XMM_YeW):
SELECT *
FROM dbo.MessageLast c
WHERE c.Stat_Date >= '2017-04-25'
AND c.Stat_Date <= '2017-04- 26'
AND c.partner_id IN (111294, 100001, 111295, 111435, 111296, 118155,111498, 118397);
第二次查询错误,使用idex扫描(https://www.brentozar.com/pastetheplan/?id=H1uvEdFgZ):
CREATE TABLE #t (partner_id Int primary key clustered);
INSERT INTO #t(partner_id)
values (111294), (100001), (111295), (111435), (111296), (118155),(111498), (118397);
SELECT *
FROM dbo.MessageLast c
where c.Stat_Date >= '2017-04-25'
and c.Stat_Date <= '2017-04- 26'
and c.partner_id in (select partner_id from #t);
使用EXISTS进行的第三次查询也很糟糕(https://www.brentozar.com/pastetheplan/?id=ryk3IntgZ):
SELECT *
FROM dbo.MessageLast c with (forceseek)
WHERE c.Stat_Date >= '2017-04-25'
and c.Stat_Date <= '2017-04-26'
and exists(select
*
from #d as d where c.partner_id = d.partner_id)
更改表变量或标准表上的临时表#t
没有帮助 - 与第二个查询相同的计划。
简单的演示脚本:
create table _tBig (
dt Date
, id1 Int
, id2 Int
, id3 Int
, id4 Int
, txt Varchar(500)
)
create clustered index PK_tBig on _tBig (id4,dt)
--truncate table _tBig
declare @i Int = 1
set nocount on
while @i < 10000
begin
insert into _tBig with (tablock)
(dt
, id1
, id2
, id3
, id4
, txt
)
select top (1000)
DateAdd(day, Rand() * 365 + 1, GetDate())
, Row_Number() over (order by O.[object_id])
, Rand() * 10000000 + 1
, Rand() * 10000000 + 1
, Rand() * 10000000 + 1
, NewId()
from sys.all_objects O
set @i += 1
end
create table _tId (id1 Int)
--truncate table _tId
insert into _tId
(id1
)
select top (5)
Row_Number() over (order by O.[object_id])
from sys.all_objects O
select *
from _tBig as tb
where tb.dt >= '20170517'
and tb.dt < '20170519'
and tb.id1 in (1, 2, 3, 4, 5)
create index IX_Big on _tBig (dt,id1)
select *
from _tBig as tb
inner join _tId as ti on ti.id1 = tb.id1
where tb.dt >= '20170517'
and tb.dt < '20170519'
create index IX_Big2 on _tBig (id1,dt)
select *
from _tBig as tb
inner join _tId as ti on ti.id1 = tb.id1
where tb.dt >= '20170517'
and tb.dt < '20170519'
--drop table dbo._tBig
--drop table dbo._tId
答案 0 :(得分:0)
你应该尝试:
SELECT *
FROM dbo.MessageLast c
JOIN #t t on c.partner_id = t.partner_id
where c.Stat_Date >= '2017-04-25'
and c.Stat_Date <= '2017-04- 26'
答案 1 :(得分:0)
这是因为索引未覆盖:您正在选择表中的所有字段。
当索引未覆盖查询sql server时,请执行以下两个步骤:
1)索引寻找找到mathed谓词
的PK值(并包括列数)2)密钥查找(在聚簇索引中搜索)每行以查找未包含在索引中的列的值。
因此,在某些情况下,查询优化器会确定全表扫描比这两个步骤更快。
您可以将SELECT *
替换为SELECT dt
(制作索引覆盖)并获得索引搜索。以下是更多信息:What is a Covered Index?