Pet*_*ock 3 index sql-server-2005
当两个值(原始表及其查找的表)都是整数时,我一直试图弄清楚为什么这个查询(对整数)使用索引扫描。
第一部分用于用值填充表格。
第二部分是我正在处理的搜索查询。如果在查询上运行执行计划,您将看到即使intcol上有一个索引,并且 #temp 表的类型为int,它仍然使用索引扫描并扫描所有 298 000 行。
问题是我正在使用的查询,它具有 (a = a) 或 (b = b)
当我取出“或(b = b)”时,它不会进行索引扫描。但是我需要“or (b == b)”来完成这个复杂的查询工作。
CREATE TABLE dbo.TestImplicitConverts
(
RowID int NOT NULL IDENTITY (1, 1),
BigIntCol bigint NOT NULL,
BitCol bit NOT NULL,
CharCol char(10) NOT NULL,
DateTimeCol datetime NOT NULL,
DecimalCol decimal(10, 2) NOT NULL ,
FloatCol float(53) NOT NULL ,
IntCol int NOT NULL,
MoneyCol money NOT NULL,
NCharCol nchar(10) NOT NULL,
NumericCol numeric(10, 2) NOT NULL,
NVarchrCol nvarchar(50) NOT NULL,
RealCol real NOT NULL,
SmallDateTimeCol smalldatetime NOT NULL,
SmallIntCol smallint NOT NULL,
SmallMoneyCol smallmoney NOT NULL,
TinyIntCol tinyint NOT NULL,
GUIDCol uniqueidentifier NOT NULL,
VarcharCol varchar(50) NOT NULL,
CONSTRAINT PK_TestImplicitConverts PRIMARY KEY CLUSTERED (RowID)
)
GO
-- Create nonclustered indexes on all columns to test implicit conversion affects
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_BigIntCol ON dbo.TestImplicitConverts (BigIntCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_BitCol ON dbo.TestImplicitConverts (BitCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_CharCol ON dbo.TestImplicitConverts (CharCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_DateTimeCol ON dbo.TestImplicitConverts (DateTimeCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_DecimalCol ON dbo.TestImplicitConverts (DecimalCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_FloatCol ON dbo.TestImplicitConverts (FloatCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_GUIDCol ON dbo.TestImplicitConverts (GUIDCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_NVarcharCol ON dbo.TestImplicitConverts (NVarchrCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_RealCol ON dbo.TestImplicitConverts (RealCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_SmallDateTimeCol ON dbo.TestImplicitConverts (SmallDateTimeCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_SmallIntCol ON dbo.TestImplicitConverts (SmallIntCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_IntCol ON dbo.TestImplicitConverts (IntCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_MoneyCol ON dbo.TestImplicitConverts (MoneyCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_NCharCol ON dbo.TestImplicitConverts (NCharCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_NumericCol ON dbo.TestImplicitConverts (NumericCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_SmallMoneyCol ON dbo.TestImplicitConverts (SmallMoneyCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_TinyIntCol ON dbo.TestImplicitConverts (TinyIntCol);
GO
CREATE NONCLUSTERED INDEX IX_TestImplicitConverts_VarcharCol ON dbo.TestImplicitConverts (VarcharCol);
GO
INSERT INTO dbo.TestImplicitConverts
( BigIntCol, BitCol, CharCol, DateTimeCol,
DecimalCol, FloatCol, IntCol, MoneyCol, NCharCol, NumericCol, NVarchrCol, RealCol,
SmallDateTimeCol, SmallIntCol, SmallMoneyCol, TinyIntCol, GUIDCol, VarcharCol)
SELECT a.number, a.number%1, CAST(b.name AS CHAR(10)), DATEADD(ms, -1*a.number, GETDATE()),
a.number, a.number, a.number, a.number, CAST(b.name AS NCHAR(10)), a.number, b.name, a.number,
DATEADD(ms, -1*a.number, GETDATE()), a.number, a.number, a.number%255, NEWID(), b.name
FROM master.dbo.spt_values AS a
CROSS JOIN master.dbo.spt_values AS b
WHERE a.type = N'P'
AND a.number < 1000
AND b.name IS NOT NULL;
GO
ALTER INDEX ALL ON TestImplicitConverts REBUILD;
GO
Run Code Online (Sandbox Code Playgroud)
create table #temp(myint int, my2ndint int)
insert into #temp(myint, my2ndint)
select 800,140
while @@rowcount>0
begin
insert into #temp(myint,my2ndint)
SELECT intcol, intcol
FROM TestImplicitConverts
WHERE
(
intcol in (select myint from #temp )
and
intcol not in (select my2ndint from #temp)
)
or (
intcol in (select my2ndint from #temp )
and
intcol not in (select myint from #temp )
)
end
drop table #temp
Run Code Online (Sandbox Code Playgroud)
你的谓词是这样的形式
WHERE (A AND NOT B) OR (B AND NOT A)
Run Code Online (Sandbox Code Playgroud)
在 SQL Server 2008 上进行测试并FORCESEEK
提示它无法生成计划。
如果您将它们重新排列为
WHERE (A OR B) AND NOT (A AND B)
Run Code Online (Sandbox Code Playgroud)
然后您可以通过搜索获得一个计划(不需要提示)。
SELECT intcol,
intcol
FROM TestImplicitConverts
WHERE ( ( intcol IN (SELECT myint
FROM #temp) )
OR ( intcol IN (SELECT my2ndint
FROM #temp) ) )
AND NOT ( intcol IN (SELECT myint
FROM #temp)
AND intcol IN (SELECT my2ndint
FROM #temp) )
Run Code Online (Sandbox Code Playgroud)
或者另一种可能性是
WITH T
AS (SELECT DISTINCT ISNULL(t1.myint, t2.my2ndint) AS intcol
FROM #temp t1
FULL OUTER JOIN #temp t2
ON t1.myint = t2.my2ndint
WHERE t1.myint IS NULL
OR t2.my2ndint IS NULL)
SELECT T.intcol,
T.intcol
FROM T
JOIN TestImplicitConverts TIC
ON TIC.intcol = T.intcol
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
291 次 |
最近记录: |