繁体   English   中英

为什么优化器在联接时不使用索引查找

[英]Why Optimizer Does Not Use Index Seek on Join

我不知道为什么下面的SELECT语句(下面)不使用索引搜索,而是使用索引扫描。 仅仅是因为行数太少还是我错过了什么?

测试数据:

-- Init Tables

IF OBJECT_ID ( 'tempdb..#wat' ) IS NOT NULL
DROP TABLE #wat;

IF OBJECT_ID ( 'tempdb..#jam' ) IS NOT NULL
DROP TABLE #jam;

CREATE TABLE #wat (
ID INT IDENTITY(1,1) NOT NULL,
Name VARCHAR(15) NOT NULL,
Den DATETIME NOT NULL
)

CREATE TABLE #jam (
ID INT IDENTITY(1,1) NOT NULL,
Name VARCHAR(15) NOT NULL
)

-- Populate Temp Tables with Random Data

DECLARE @length INT
       ,@charpool VARCHAR(255)
       ,@poolLength INT
       ,@RandomString VARCHAR(255)
       ,@LoopCount INT

SET @Length = RAND() * 5 + 8
SET @CharPool = 'abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789'
SET @PoolLength = LEN(@CharPool)
SET @LoopCount = 0
SET @RandomString = ''

WHILE (@LoopCount < 500) 
BEGIN

    INSERT INTO #jam (Name)
    SELECT    SUBSTRING(@Charpool, CONVERT(int, RAND() * @PoolLength), 5)
    SET @LoopCount = @LoopCount + 1

END

-- Insert Rows into Second Temp Table
INSERT INTO #wat( Name, Den )
SELECT TOP 50 Name, GETDATE()
FROM #jam

-- Create Indexes

--DROP INDEX IX_jedna ON #jam
--DROP INDEX IX_dva ON #wat
CREATE INDEX IX_jedna ON #jam (Name) INCLUDE (ID);
CREATE INDEX IX_dva ON #wat (Name) INCLUDE (ID, Den);

-- Select

SELECT *
FROM #jam j
JOIN #wat w
ON w.Name = j.Name

执行计划:

在此处输入图片说明

优化器有几种方法可以做乔恩: nested loops, hash match or merge join联接(您的情况),并且可能是另一种方法。 根据您的数据:行数,现有索引和统计ID确定哪个更好。

在您的示例中,优化器假定存在多对多关系。 并且您有两个表都被此字段soret(索引)。

为什么合并联接? -从逻辑上讲-并行浏览两个表。 服务器将只需要执行一次。

为了进行所需的seek ,服务器必须一次移动第一个表,并且必须多次在第二个表中进行查找,因为所有记录在另一个表中都有匹配项。 服务器将根据需要读取所有记录。 而且,使用搜寻时没有任何利润(1000次搜寻比遍历1000条记录的一个简单循环还要困难)。

如果要seek ,请在查询中添加一些没有匹配项和where子句的记录。

UPD

甚至添加简单

where j.ID = 1

给你seek

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM