SQL Server 中的 INNER JOIN 与 LEFT JOIN 性能

2024-03-08

我创建了在 9 个表上使用 INNER JOIN 的 SQL 命令,无论如何这个命令需要很长时间(超过五分钟)。因此,我的家人建议我将 INNER JOIN 更改为 LEFT JOIN,因为 LEFT JOIN 的性能更好,尽管我知道。改了之后,查询速度明显提高了。

我想知道为什么 LEFT JOIN 比 INNER JOIN 快?

Mysql 命令如下所示:SELECT * FROM A INNER JOIN B ON ... INNER JOIN C ON ... INNER JOIN D等等

Update:这是我的架构的简要说明。

FROM sidisaleshdrmly a -- NOT HAVE PK AND FK
    INNER JOIN sidisalesdetmly b -- THIS TABLE ALSO HAVE NO PK AND FK
        ON a.CompanyCd = b.CompanyCd 
           AND a.SPRNo = b.SPRNo 
           AND a.SuffixNo = b.SuffixNo 
           AND a.dnno = b.dnno
    INNER JOIN exFSlipDet h -- PK = CompanyCd, FSlipNo, FSlipSuffix, FSlipLine
        ON a.CompanyCd = h.CompanyCd
           AND a.sprno = h.AcctSPRNo
    INNER JOIN exFSlipHdr c -- PK = CompanyCd, FSlipNo, FSlipSuffix
        ON c.CompanyCd = h.CompanyCd
           AND c.FSlipNo = h.FSlipNo 
           AND c.FSlipSuffix = h.FSlipSuffix 
    INNER JOIN coMappingExpParty d -- NO PK AND FK
        ON c.CompanyCd = d.CompanyCd
           AND c.CountryCd = d.CountryCd 
    INNER JOIN coProduct e -- PK = CompanyCd, ProductSalesCd
        ON b.CompanyCd = e.CompanyCd
           AND b.ProductSalesCd = e.ProductSalesCd 
    LEFT JOIN coUOM i -- PK = UOMId
        ON h.UOMId = i.UOMId 
    INNER JOIN coProductOldInformation j -- PK = CompanyCd, BFStatus, SpecCd
        ON a.CompanyCd = j.CompanyCd
            AND b.BFStatus = j.BFStatus
            AND b.ProductSalesCd = j.ProductSalesCd
    INNER JOIN coProductGroup1 g1 -- PK = CompanyCd, ProductCategoryCd, UsedDepartment, ProductGroup1Cd
        ON e.ProductGroup1Cd  = g1.ProductGroup1Cd
    INNER JOIN coProductGroup2 g2 -- PK = CompanyCd, ProductCategoryCd, UsedDepartment, ProductGroup2Cd
        ON e.ProductGroup1Cd  = g2.ProductGroup1Cd

A LEFT JOIN绝对不比INNER JOIN。事实上,它更慢;根据定义,外连接 (LEFT JOIN or RIGHT JOIN)必须完成一个的所有工作INNER JOIN加上对结果进行空扩展的额外工作。它还预计会返回更多行,从而进一步增加总执行时间,因为结果集的大小较大。

(并且即使LEFT JOIN were更快地specific由于一些难以想象的因素的综合作用,它在功能上并不等同于INNER JOIN,因此您不能简单地将一个实例的所有实例替换为另一个实例!)

您的性能问题很可能出在其他地方,例如没有正确索引候选键或外键。 9 张桌子需要加入的数量相当多,因此几乎任何地方都会出现速度减慢的情况。如果您发布您的架构,我们也许能够提供更多详细信息。


Edit:

进一步思考这一点,我可以想到一种情况,在这种情况下LEFT JOIN可能比INNER JOIN,那就是:

  • 一些表是very小(例如,10 行以下);
  • 表没有足够的索引来覆盖查询。

考虑这个例子:

CREATE TABLE #Test1
(
    ID int NOT NULL PRIMARY KEY,
    Name varchar(50) NOT NULL
)
INSERT #Test1 (ID, Name) VALUES (1, 'One')
INSERT #Test1 (ID, Name) VALUES (2, 'Two')
INSERT #Test1 (ID, Name) VALUES (3, 'Three')
INSERT #Test1 (ID, Name) VALUES (4, 'Four')
INSERT #Test1 (ID, Name) VALUES (5, 'Five')

CREATE TABLE #Test2
(
    ID int NOT NULL PRIMARY KEY,
    Name varchar(50) NOT NULL
)
INSERT #Test2 (ID, Name) VALUES (1, 'One')
INSERT #Test2 (ID, Name) VALUES (2, 'Two')
INSERT #Test2 (ID, Name) VALUES (3, 'Three')
INSERT #Test2 (ID, Name) VALUES (4, 'Four')
INSERT #Test2 (ID, Name) VALUES (5, 'Five')

SELECT *
FROM #Test1 t1
INNER JOIN #Test2 t2
ON t2.Name = t1.Name

SELECT *
FROM #Test1 t1
LEFT JOIN #Test2 t2
ON t2.Name = t1.Name

DROP TABLE #Test1
DROP TABLE #Test2

如果您运行它并查看执行计划,您将看到INNER JOIN查询确实比LEFT JOIN,因为它满足上述两个条件。这是因为 SQL Server 想要对以下内容进行哈希匹配:INNER JOIN,但是嵌套循环LEFT JOIN;前者是normally快得多,但由于行数太少and没有可用的索引,散列操作是查询中最昂贵的部分。

通过用您最喜欢的编程语言编写程序,对具有 5 个元素的列表(与具有 5 个元素的哈希表)执行大量查找,您可以看到相同的效果。由于大小的原因,哈希表版本实际上更慢。但如果将其增加到 50 个元素,或 5000 个元素,列表版本就会慢得像爬行一样,因为哈希表的 O(N) 与 O(1) 相比。

但将此查询更改为ID列而不是Name你会看到一个非常不同的故事。在这种情况下,它会为两个查询执行嵌套循环,但是INNER JOIN版本能够用搜索替换聚集索引扫描之一 - 这意味着这实际上是一个数量级行数较多时速度更快。

所以结论或多或少就是我上面几段提到的;这几乎肯定是索引或索引覆盖问题,可能与一个或多个非常小的表结合在一起。这些是 SQL Server 运行的唯一情况might有时会选择一个更差的执行计划INNER JOIN than a LEFT JOIN.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQL Server 中的 INNER JOIN 与 LEFT JOIN 性能 的相关文章

  • 自动删除主键序列中的间隙

    我正在创建一个网页 该网页根据用户操作将数据存储到 MySQL 数据库中 数据库有很多行 行的主键是列 rowID 它只是按顺序对行进行编号 例如 1 2 3 4 用户可以选择删除行 问题是当用户删除最后一行以外的行时 rowID 中有一个
  • Rails Windows Vagrant 响应时间非常慢

    我在跑 Vagrant 1 7 1 Rails 4 1 4 Thin 1 6 1 Windows 7 每个静态文件的发送时间都超过一秒 在我的 PC 上加载一个页面可能需要大约 20 秒 而在同事的 Linux 机器上则只需瞬间 有一些帖子
  • 红宝石接球和效率

    catch在 Ruby 中意味着跳出深度嵌套的代码 在 Java 中 例如用Java也可以达到同样的效果try catch用于处理异常 但它被认为是糟糕的解决方案 而且效率非常低 在 Ruby 中 我们有处理异常的方法begin raise
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • 标量子查询包含多行

    我正在使用 H2 数据库并想要移动一些数据 为此 我创建了以下查询 UPDATE CUSTOMER SET EMAIL SELECT service EMAIL FROM CUSTOMER SERVICE AS service INNER
  • 没有为 1 个或多个必需参数给出值。更新SQL

    我正在编写一个程序 当用户在列表视图上选择记录时 该程序会更新密码或积分 我收到错误 没有为 1 个或多个必需参数给出值 我不知道如何纠正 我是否遗漏了一些明显的东西 Dim sql As String UPDATE Users SET P
  • 使用 FileInputStream 时如何确定理想的缓冲区大小?

    我有一个从文件创建 MessageDigest 哈希 的方法 我需要对很多文件 gt 100 000 执行此操作 用于读取文件的缓冲区应该设置多大才能最大限度地提高性能 大多数人都熟悉基本代码 为了以防万一 我将在这里重复一遍 Messag
  • 带有可变 WHERE 子句的批量 UPDATE 表

    我有一堆值对 foo1 bar1 foo2 bar2 我想做一堆更新 将 foo 列设置为 foo1 其中 bar 列为 bar1 我正在使用 psycopg2 在 Python 中执行此操作 我可以executemany与查询UPDATE
  • * 到底有多慢?

    大家都表示 选择器非常慢 但它到底有多慢呢 我总是试图避免它 但有时它非常有用 例如 h1 margin top 1em 简单来说 通用选择器 速度只与页面上的元素一样慢 Since 从右到左匹配浏览器获取每个元素并将其与所有候选规则进行匹
  • 在 C# 中执行基于存储过程的查询后,如何重新使用 CommandText 的 SqlCommand 对象?

    我有一个示例代码 aCommand CommandType CommandType StoredProcedure aCommand Parameters AddWithValue book id bookID aCommand Param
  • 将两个表合并为一个输出

    假设我有两张表 已知营业时间 ChargeNum CategoryID Month Hours 111111 1 2 1 09 10 111111 1 3 1 09 30 111111 1 4 1 09 50 222222 1 3 1 09
  • 3 个表的 SQL 查询(或联接)

    第一次在 Stack Overflow 上问问题 很棒的资源 但是只有一件事真正让我作为 SQL 新手感到困惑 我有三个表 我想获取与鲍勃的学生相关的所有导师的姓名 表 1 教师 ID Name 1 Bob 表 2 学生 STUDENT I
  • 为 PostgreSQL 查询选择正确的索引

    简化表 CREATE TABLE products product no integer PRIMARY KEY sales integer status varchar 16 category varchar 16 CREATE INDE
  • SQL 使用另一列的键和最大值设置列

    我需要根据同一 ID 的 duration 列的最大值更新 max register 列 将值设置为 1 其他值设置为 0 初始表 Id duration max register 1 0 0 1 7 0 1 3 0 2 10 0 2 5
  • 为什么n++执行速度比n=n+1快?

    在C语言中 为什么n 执行速度快于n n 1 int n n int n n n 1 我们的老师在今天的课堂上问了这个问题 这不是家庭作业 如果您正在开发一个 石器时代 编译器 的情况下 石器时代 n比n 比n n 1 机器通常有incre
  • mysql表中的数据非常大。即使 select 语句也需要很多时间

    我正在开发一个数据库 它是一个相当大的数据库 有 13 亿行和大约 35 列 这是我检查表状态后得到的结果 Name Table Name Engine InnoDB Version 10 Row format Compact Rows 1
  • 获取mysql中逗号分隔行中不同值的计数

    一个表 Jobs 有 2 列 JobId 城市 当我们保存工作时 工作位置可能是多个城市 如下所示 JobId City 1 New York 2 New York Ohio Virginia 3 New York Virginia 我如何
  • 更改mysql数据库表中的日期格式

    大家早上好 只是一个简单的问题 在我现有的 MySql 数据库中 我几乎没有包含日期 的列 目前这些是年 月 日格式 但现在我需要将其全部更改为年 月 日格式 我试过了select date format curdate d m Y 但它不
  • 在同一查询中选择 Count of ip 和 Count of DISTINCT ip

    我有一个这样的表结构 TABLE NAME counter id datetime url ip 1 2013 04 12 13 27 09 url1 ip01 2 2013 04 13 10 55 43 url2 ip02 3 2013
  • NHibernate - CreateCriteria 与 CreateAlias

    假设以下场景 class Project public Job Job class Job public Name 假设我想使用 Criteria API 搜索其 Job 名称为 sumthing 的所有项目 我可以使用 CreateAli

随机推荐