【问题标题】:selecting keys which are not in another table takes forever选择不在另一个表中的键需要永远
【发布时间】:2020-08-20 11:27:12
【问题描述】:

我有一个这样的查询:

select key, name from localtab where key not in (select key from remotetab);

查询需要很长时间,我不明白为什么。

localtab 是本地表,remotetab 是另一个服务器中的远程表。 key 是一个 int 列,在两个表中都有唯一索引。当我分别查询这两个表时,只需几秒钟。

【问题讨论】:

  • "并且 remotetab 是另一个服务器中的远程表。" 你的问题。对于这样的远程查询,需要将 整个 表从远程实例传输到本地实例,然后针对从该传输创建的临时对象执行过滤(这将最可能是在tempdb 中创建的工作表)。
  • 好的,但是独立的select * from remotetab 确实只需要几秒钟(在这种情况下所有数据都已传输)。我们谈论大约 100.000 条记录。
  • 可能是localtab中的每一行都会有一次传输和扫描,而不是1次传输然后扫描localtab中的所有行的表。这就是为什么 vvvv4d 所建议的可能具有非常不同的性能。此外,正如我所提到的,整个表被传输,所以不仅仅是key列的值,而是所有列的值。
  • 啊好吧!是的,我假设只有一次远程表传输!但似乎这个假设是不正确的。不使用临时表还有其他想法吗?
  • “还有什么不使用临时表的想法吗?” 临时表通常是这里的方式。否则,您需要研究一种将数据从远程实例复制到本地实例的方法,然后(本地)实例可以执行足够的查找操作。

标签: sql-server sql-server-2014


【解决方案1】:

链接服务器的性能很差。将您需要的数据获取到本地服务器并在那里完成大部分繁重的工作和处理,而不是在单个查询中混合本地和远程。

selectremotetab 进入临时表

select [key] into #remote_made_local from remotetab

在执行 where 子句过滤时使用 #temp 表并使用 exists 而不是 in 以获得更好的性能

select a.[key], a.name from localtab a where not exists (select 1 from #remote_made_local b where b.[key] = a.[key] )

相对于做

select [key], name from localtab where key not in (select [key] from #remote_made_local)

【讨论】:

  • 为了额外的好处,最好在临时表的key 列上放置一个索引。此外,key 需要分隔标识,因为KEY 是保留关键字。理想情况下,此类词不应用于对象名称。
【解决方案2】:

还有一个不使用临时表的解决方案。

通过使用left join 而不是not in (select ...),您可以大大加快查询速度。像这样:

select l.key, l.name
from  localtab l left join remotetab r on l.key = r.key
where r.key is null ;

【讨论】:

  • 谢谢,这个速度快很多,而且它在没有临时表的情况下也能工作!似乎优化器正在处理与in 子句不同的left join。我会将您的帖子标记为答案,因为它不需要临时表。不过,另一个答案也不错,可能速度更快。
猜你喜欢
  • 2015-03-28
  • 1970-01-01
  • 1970-01-01
  • 2018-01-23
  • 2019-12-08
  • 2013-12-08
  • 2011-01-30
  • 2013-04-22
  • 2023-03-20
相关资源
最近更新 更多