SQL Server查询优化器执行不必要的联接

德米特里一世

我想知道是否有人可以阐明为什么SQL Server(在我的情况下为2016 RTM,但我怀疑这不是特定于版本的)为什么要执行此看似不必要的INNER JOIN。

考虑以下两个由外键连接的表:

CREATE TABLE [dbo].[batches](
[Id] [smallint] IDENTITY(1,1) PRIMARY KEY,
[Date] [date] NOT NULL,
[Run] [tinyint] NOT NULL,
[Clean] [bit] NOT NULL) 

CREATE TABLE [dbo].[batch_values](
[Batch_Id] [smallint] NOT NULL,
[Key] [int] NOT NULL,
[Value] [int] NOT NULL,
CONSTRAINT [PK_batch_values] PRIMARY KEY CLUSTERED 
( [Batch_Id] ASC, [Key] ASC))
GO 

ALTER TABLE [dbo].[batch_values]  WITH CHECK 
ADD  CONSTRAINT  [FK_batch_values_batches] FOREIGN KEY([Batch_Id])
REFERENCES [dbo].[batches] ([Id])
GO

ALTER TABLE [dbo].[batch_values] CHECK CONSTRAINT [FK_batch_values_batches]
GO

用一些数据填充表:

SET NOCOUNT ON;

DECLARE 
    @BatchCount int,
    @BatchId smallint,
    @KeyCount int;

SET @BatchCount = 1;

WHILE @BatchCount <= 100
BEGIN

    INSERT INTO dbo.[batches]
    VALUES (DATEADD(dd, @BatchCount / 10, '2016-01-01'), @BatchCount % 10, @BatchCount % 2);

    SET @BatchId = SCOPE_IDENTITY();

    SET @KeyCount = 1;

    WHILE @KeyCount <= 1000
    BEGIN

        INSERT INTO dbo.batch_values
        VALUES (@BatchId, @KeyCount, RAND() * 1000000 - 500000);

        SET @KeyCount = @KeyCount + 1;

    END;

    SET @BatchCount = @BatchCount + 1;

END;

现在,如果我运行以下查询,执行计划将显示SQL Server正在对[batches]表执行INNER JOIN,即使未从中选择任何列,因此也无法从[batch_values]中删除任何记录由于外键约束的联接数。

查询和执行计划的屏幕截图

在我看来,Query Optimizer应该将INNER JOIN丢弃为不必要的,而只是对[batch_values]进行主键查找,但事实并非如此。

这很重要,因为如果我开发连接多个表的视图以呈现基础数据的“大图”以便于使用,那么在查询这些视图时,我会受到性能的影响。

安东

通过SQL Optimizer使用JOIN ELIMINATION有很多限制

例如,如果您在外键中使用多个列,或者约束不受信任,或者标记为“非用于复制”等。

如果您用外键中的列指定WHERE谓词,则SQL Server可能不使用JOIN ELIMINATION。

从WHERE中删除WHERE或删除“ Batch_id = 100”,您应该看到优化器现在使用JOIN ELIMINATION

文档仅限于此主题,因此我无法提供证明链接,但是许多人在过去5-7年中针对不同版本报告了此问题,并同意行为是设计使然。我的建议是引发MS事件,并直接询问他们是否对您的系统至关重要。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在SQL查询中找到不必要的联接?

来自分类Dev

花费时间优化sql查询VS从数据库推送不必要的数据

来自分类Dev

为什么SQL Server的查询优化器将表与其自身联接?

来自分类Dev

为什么SQL Server的查询优化器将表与其自身联接?

来自分类Dev

为什么EF生成带有不必要的空检查的SQL查询?

来自分类Dev

SQL查询优化-添加联接等

来自分类Dev

使用联接优化 SQL 查询

来自分类Dev

SQL Server查询优化:自我内部联接过多

来自分类Dev

在SQL Server中除以十进制类型会导致不必要的尾随零

来自分类Dev

使用SPARK(SQL)删除不必要的JSON字段

来自分类Dev

如何在SQL中删除不必要的字符

来自分类Dev

优化SQL分组依据和联接查询

来自分类Dev

优化包含左联接的SQL查询

来自分类Dev

通过多个联接优化SQL查询

来自分类Dev

优化SQL分组依据和联接查询

来自分类Dev

优化包含左联接的SQL查询

来自分类Dev

优化SQL Server 2012查询

来自分类Dev

优化SQL Server聚合查询

来自分类Dev

优化SQL Server 2012查询

来自分类Dev

SQL Server中的查询优化

来自分类Dev

SQL Server 排名查询优化

来自分类Dev

优化我的 SQL Server 查询

来自分类Dev

相关嵌套查询的查询优化(SQL Server)

来自分类Dev

SQL Server游标-遍历多个服务器并执行查询

来自分类Dev

SQL Server查询分析器与执行计划

来自分类Dev

Linq中的特定查询它与SQL Server中的内部联接执行的功能不同

来自分类Dev

SQL引擎/优化器可以使用临时表执行查询吗?

来自分类Dev

执行递归SQL查询(SQL Server 2005)

来自分类Dev

sql链接服务器联接查询