sql-server – 为什么更改声明的连接列顺序会引入排序?

前端之家收集整理的这篇文章主要介绍了sql-server – 为什么更改声明的连接列顺序会引入排序?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有两个具有相同名称,类型和索引键列的表.其中一个具有唯一的聚簇索引,另一个具有非唯一的索引.

测试设置

安装脚本,包括一些实际的统计信息

DROP TABLE IF EXISTS #left;
DROP TABLE IF EXISTS #right;

CREATE TABLE #left (
    a       char(4) NOT NULL,b       char(2) NOT NULL,c       varchar(13) NOT NULL,d       bit NOT NULL,e       char(4) NOT NULL,f       char(25) NULL,g       char(25) NOT NULL,h       char(25) NULL
    --- and a few other columns
);

CREATE UNIQUE CLUSTERED INDEX IX ON #left (a,b,c,d,e,f,g,h)

UPDATE STATISTICS #left WITH ROWCOUNT=63800000,PAGECOUNT=186000;

CREATE TABLE #right (
    a       char(4) NOT NULL,h       char(25) NULL
    --- and a few other columns
);

CREATE CLUSTERED INDEX IX ON #right (a,h)

UPDATE STATISTICS #right WITH ROWCOUNT=55700000,PAGECOUNT=128000;

复制品

当我在他们的集群键上加入这两个表时,我希望有一对多的MERGE连接,如下所示:

SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
    l.a=r.a AND
    l.b=r.b AND
    l.c=r.c AND
    l.d=r.d AND
    l.e=r.e AND
    l.f=r.f AND
    l.g=r.g AND
    l.h=r.h
WHERE l.a='2018';

这是我想要的查询计划:

(别介意警告,它们与虚假统计数据有关.)

但是,如果我在连接中更改列的顺序,如下所示:

SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
    l.c=r.c AND     -- used to be third
    l.a=r.a AND     -- used to be first
    l.b=r.b AND     -- used to be second
    l.d=r.d AND
    l.e=r.e AND
    l.f=r.f AND
    l.g=r.g AND
    l.h=r.h
WHERE l.a='2018';

… 有时候是这样的:

Sort运算符似乎根据声明的连接顺序对流进行排序,即c,a,h,这会向我的查询计划添加阻塞操作.

我看过的东西

>我已经尝试将列更改为NOT NULL,结果相同.
>原始表是使用ANSI_PADDING OFF创建的,但使用ANSI_PADDING ON创建它不会影响此计划.
>我尝试了INNER JOIN而不是LEFT JOIN,没有变化.
>我在2014 SP2 Enterprise上发现了它,在2017 Developer(当前CU)上创建了一个repro.
>删除前导索引列上的WHERE子句会生成好的计划,但它会影响结果.. 原文链接:https://www.f2er.com/mssql/79493.html

猜你在找的MsSQL相关文章