加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

sql-server – 在不返回任何行的查询中包括ORDER BY会严峻影响性

发布时间:2021-05-24 19:15:10 所属栏目:编程 来源:网络整理
导读:给定一个简朴的三表毗连,纵然没有返回任何行,当包括ORDER BY时,查询机能也会产生庞大变革.现实题目场景必要30秒才气返回零行,但在不包罗ORDER BY时是即时的.为什么? SELECT * FROM tinytable t /* one narrow row */JOIN smalltable s on t.id=s.tinyId /* o

给定一个简朴的三表毗连,纵然没有返回任何行,当包括ORDER BY时,查询机能也会产生庞大变革.现实题目场景必要30秒才气返回零行,但在不包罗ORDER BY时是即时的.为什么?

SELECT * 
FROM tinytable t                          /* one narrow row */
JOIN smalltable s on t.id=s.tinyId        /* one narrow row */
JOIN bigtable b on b.smallGuidId=s.GuidId /* a million narrow rows */
WHERE t.foreignId=3                       /* doesn't match */
ORDER BY b.CreatedUtc          /* try with and without this ORDER BY */

我知道我可以在bigtable.smallGuidId上有一个索引,可是,我以为在这种环境下现实上会让它变得更糟.

这是建设/添补表以供测试的剧本.稀疏的是,小型表具有nvarchar(max)字段好像很重要.我好像很重要的是我用一个guid插手bigtable(我猜它想要行使哈希匹配).

CREATE TABLE tinytable
  (
     id        INT PRIMARY KEY IDENTITY(1,1),foreignId INT NOT NULL
  )

CREATE TABLE smalltable
  (
     id     INT PRIMARY KEY IDENTITY(1,GuidId UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID(),tinyId INT NOT NULL,Magic  NVARCHAR(max) NOT NULL DEFAULT ''
  )

CREATE TABLE bigtable
  (
     id          INT PRIMARY KEY IDENTITY(1,CreatedUtc  DATETIME NOT NULL DEFAULT GETUTCDATE(),smallGuidId UNIQUEIDENTIFIER NOT NULL
  )

INSERT tinytable
       (foreignId)
VALUES(7)

INSERT smalltable
       (tinyId)
VALUES(1)

-- make a million rows 
DECLARE @i INT;

SET @i=20;

INSERT bigtable
       (smallGuidId)
SELECT GuidId
FROM   smalltable;

WHILE @i > 0
  BEGIN
      INSERT bigtable
             (smallGuidId)
      SELECT smallGuidId
      FROM   bigtable;

      SET @i=@i - 1;
  END

我已经在SQL 2005,2008和2008R2上测试了沟通的功效.

办理要领

我赞成马丁史女士的谜底,但题目不只仅是统计数据之一. foreignId列的统计信息(假设已启用自动统计信息)精确表现值3不存在任何行(只有一行,值为7):
DBCC SHOW_STATISTICS (tinytable,foreignId) WITH HISTOGRAM

SQL Server知道自捕捉统计信息后工作也许已产生变动,因此在执行打算时也许会有一行值为3.另外,在打算编译和执行之间也许会颠末任何时刻(事实,打算被缓存以便重用).正如Martin所说,SQL Server包括的逻辑用于检测何时举办了足够的修改以证明为了最优缘故起因而从头编译任何缓存的打算.

然而,这些最终都不重要.在一个边沿环境破例环境下,优化器永久不会将表操纵发生的行数预计为零.假如它可以静态地确定输出必需始终为零行,则操纵是冗余的而且将被完全删除.

优化器的模子改为预计起码一行.假如也许的预计值较低,回收这种开导式要领每每会发生更好的均匀打算.从处理赏罚流中的那一点开始,在某个阶段发生零行预计的打算将是无用的,由于没有基原本举办基于本钱的决定(零行是零行,无论怎样).假如预计功效是错误的,那么在零行预计之上的打算外形险些没有公道的机遇.

第二个身分是另一个称为截止假设的建模假设.这根基上暗示假如查询将一系列值与另一个值范畴毗连起来,那是由于范畴重叠.另一种说法就是说要指定毗连,由于估量会返回行.假如没有这种推理,凡是会低估本钱,导致对普及的常见查询的打算不佳.

从本质上讲,您所拥有的是一个不得当优化器模子的查询.我们无法通过多列或过滤索引来“改造”估算;这里没有步伐预计低于1行.一个真实的数据库也许有外键来确保不会呈现这种环境,但假设这里不合用,我们将行使提醒来更正模子外的环境.任何数目的差异提醒要领都合用于此查询. OPTION(FORCE ORDER)刚好与编写的查询一路事变.

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读