Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在vs.与大型行集连接_Sql_Sql Server 2005_Performance_Join - Fatal编程技术网

Sql 在vs.与大型行集连接

Sql 在vs.与大型行集连接,sql,sql-server-2005,performance,join,Sql,Sql Server 2005,Performance,Join,我想在主键位于另一个表中的表中选择行。我不确定是否应该在SQLServer2005中使用JOIN或IN运算符。对于大型数据集(即数百万行),这两个SQL查询之间是否存在显著的性能差异 我会使用join,打赌它会比IN快很多。当然,这假定定义了主键,从而使索引速度大大加快。对a中的每一行计算IN(并重新运行select from b),而连接优化为使用索引和其他整洁的分页技巧 不过,在大多数情况下,优化器可能能够从相关子查询中构造联接,并最终得到相同的执行计划 编辑:请阅读下面的评论进一步。。。讨

我想在主键位于另一个表中的表中选择行。我不确定是否应该在SQLServer2005中使用JOIN或IN运算符。对于大型数据集(即数百万行),这两个SQL查询之间是否存在显著的性能差异


我会使用join,打赌它会比IN快很多。当然,这假定定义了主键,从而使索引速度大大加快。

对a中的每一行计算IN(并重新运行select from b),而连接优化为使用索引和其他整洁的分页技巧

不过,在大多数情况下,优化器可能能够从相关子查询中构造联接,并最终得到相同的执行计划


编辑:请阅读下面的评论进一步。。。讨论此答案的有效性,以及OP问题的实际答案。=)

除了亲自在大量测试数据上进行实际测试之外,我想说的是使用连接。在大多数情况下,与in子查询相比,我使用它们的性能总是更好,而且在如何加入、选择什么、不选择什么等方面,您有更多的自定义选项。

它们是具有不同结果的不同查询。使用IN查询,只要谓词匹配,就会从表“a”中获得1行。使用内部联接查询,只要联接条件匹配,就会得到a*b行。 对于a中的值{1,2,3}和b中的值{1,2,2,3},你将从连接中得到1,2,2,3,从in中得到1,2,3

编辑-我想你可能会在这里遇到一些答案,这会让你产生误解。亲自去测试一下,你会发现这些都是很好的查询计划:

create table t1 (t1id int primary key clustered)
create table t2 (t2id int identity primary key clustered
    ,t1id int references t1(t1id)
)


insert t1 values (1)
insert t1 values (2)
insert t1 values (3)
insert t1 values (4)
insert t1 values (5)

insert t2 values (1)
insert t2 values (2)
insert t2 values (2)
insert t2 values (3)
insert t2 values (4)


select * from t1 where t1id in (select t1id from t2)
select * from t1 where exists (select 1 from t2 where t2.t1id = t1.t1id)
select t1.* from t1 join t2 on t1.t1id = t2.t1id

前两个计划是相同的。最后一个计划是一个嵌套循环,这种差异是可以预料的,因为正如我在上面提到的,连接具有不同的语义。

两者都没有。使用ANSI-92连接:

SELECT a.*
FROM a JOIN b a.c = b.d
然而,它最好是作为一个存在

SELECT a.*
FROM a
WHERE EXISTS (SELECT * FROM b WHERE a.c = b.d)

这将删除可能由联接生成的重复项,但运行速度即使不快也一样快

更新:

我博客中的这篇文章总结了我的答案和我对其他答案的评论,并展示了实际执行计划:


这些查询不是等价的。如果表
b
没有保留键(即
b.d
的值不是唯一的),则它们可能会产生不同的结果

第一个查询的等效项如下所示:

SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT d
        FROM    b
        ) bo
ON      a.c = bo.d
如果
b.d
唯一的
并且被标记为唯一的(使用
唯一索引
唯一约束
),那么这些查询是相同的,并且很可能会使用相同的计划,因为
SQL Server
足够聪明,可以考虑到这一点

SQL Server
可以使用以下方法之一运行此查询:

  • 如果在
    a.c
    上有一个索引,
    d
    唯一的
    b
    a
    相比相对较小,那么该条件将传播到子查询中,并使用普通的
    内部联接
    (带
    b
    前导)

  • 如果
    b.d
    上有一个索引,并且
    d
    不是
    唯一的
    ,则该条件也会传播,并使用
    左半联接
    。它也可用于上述条件

  • 如果
    b.d
    a.c
    上都有索引,并且它们都很大,则使用
    MERGE-SEMI-JOIN

  • 如果任何表上都没有索引,则在
    b
    上构建哈希表,并使用
    哈希半联接

这两种方法每次都不会重新评估整个子查询

请参阅我的博客中的这篇文章,以了解有关其工作原理的更多详细信息:


四大数据库中的所有关系数据库都有链接。

观察这两种类型的执行计划并得出结论。除非子查询在“in”语句中返回的记录数量非常少,否则in变量几乎肯定会较慢。

来自子查询基础:

许多Transact-SQL语句 包含子查询可以是 交替地表示为连接。 其他问题只能通过以下方式提出: 子查询。在Transact-SQL中,有 通常没有性能差异 在包含 子查询与语义等价 不存在的版本。然而,在 某些情况下,存在必须 如果选中,则联接会产生更好的结果 演出否则,嵌套的 必须为每个查询处理查询 外部查询的结果以确保 消除重复。这样 在这种情况下,连接方法将产生 更好的结果

在您提供的示例中,对于每个外部查询结果,嵌套查询只需要处理一次,因此应该没有性能差异。检查两个查询的执行计划应该可以确认这一点


注意:虽然问题本身没有指定SQLServer2005,但我根据问题标签的假设进行了回答。其他数据库引擎(甚至不同的SQL Server版本)可能不会以相同的方式进行优化。

一般认为,联接比in子查询更有效;但是,SQL*服务器优化器通常不会产生明显的性能差异。即使如此,最好还是使用连接条件进行编码,以保持标准的一致性。此外,如果您的数据和代码将来需要迁移,数据库引擎可能不会这么宽容(例如,在MySql中使用连接而不是子查询会产生巨大的差异)。

理论只会让您在此类问题上走得更远。在一天结束时,您将要测试这两个查询,看看哪一个实际运行得更快。我曾经遇到过这样的情况:JOIN版本需要一分钟,而t版本需要一分钟
SELECT  *
FROM    a
WHERE   a.c IN (SELECT d FROM b)

SELECT  a.*
FROM    a
JOIN    b
ON      a.c = b.d
SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT d
        FROM    b
        ) bo
ON      a.c = bo.d
SELECT a.*
FROM a LEFT OUTER JOIN b ON a.c = b.d
WHERE b.d is not null -- Given b.d is a primary Key with index