【问题标题】:Why does SELECT * INTO x FROM a JOIN b take significantly greater time than total time of SELECT COUNT(*) FROM a JOIN b & SELECT * INTO y FROM x?为什么 SELECT * INTO x FROM a JOIN b 花费的时间比 SELECT COUNT(*) FROM a JOIN b & SELECT * INTO y FROM x 的总时间长得多?
【发布时间】:2019-06-16 07:14:26
【问题描述】:

我有 2 张桌子:ab。表a 有大约100 万条记录,而表b 有大约50,000 条记录。非聚集索引在 ab 中的每个列上定义。这 2 个表是基于这些列连接的。查询如下:

SELECT * INTO x
FROM a JOIN b ON a.cola = b.colb

最终结果是大约 200 万条记录。查询大约需要 14 分钟才能完成。但是,如果我尝试使用COUNT(*) 而不是SELECT...INTO,则查询不到一分钟即可完成。

SELECT COUNT(*)
FROM a JOIN b ON a.col1 = b.col1

我假设剩下的 13 分钟是由于 I/O 操作。所以我运行了另一个查询,它刚刚从“x”中获取先前插入的数据并插入到“y”中。

SELECT * INTO y
FROM x

此查询需要 5 分钟来插入 200 万行数据。那么我的问题是第一个查询需要 14 分钟才能完成的原因是什么,而实际连接和独立插入同一组数据的总时间仅为 6 分钟。剩余8分钟的执行时间是什么原因?有什么办法可以减少这个时间吗?

我查看了第一个查询的实际执行计划。 > 95% 的时间都用在了 INSERT 操作中。 INSERT 操作只是按原样插入列 - 没有其他逻辑(如计算、CAST、CASE...WHEN 等)。我的数据库已经处于 BULK_LOGGED 恢复模式,因此这些 SELECT...INTO 操作的日志记录最少。

【问题讨论】:

  • 因为,SELECT * INTO x SQL Server 需要为 每一 行获取 每一 列的值,对于 SELECT COUNT(*) 它只需要知道有多少行。它们是完全不同的查询。想象一下,如果我让你计算一本书有多少页,并且我还让你逐页复制该书的全部内容;你真的认为你可以同时做到快/慢吗?
  • 假设 估计成本的 95% = 时间的 95% 是错误的。这只是对 I/O 和 CPU 成本的估计。操作过程中有哪些等待类型?您如何确认您获得的日志记录最少?这不仅仅取决于数据库恢复模型。

标签: sql sql-server sql-server-2012 query-optimization database-performance


【解决方案1】:

这是 I/O 操作。 JOIN 必须处理所有数据,而不仅仅是行数。您没有考虑此处理时间。

鉴于JOIN 必须完成的工作,额外的数据读/写似乎是正确的。

【讨论】:

  • 我可以采取什么措施来减少这个时间?
  • @Ral'akkai -- 获得更快的磁盘
  • @Ral'akkai 那么您想快速将 200 万行写入磁盘吗?我想在 5 分钟内而不是 30 分钟内开车上班。我可能需要一架直升飞机,或者辞掉工作,坐一架离我家更近的地方,但我无能为力。在您的情况下,您可以写入更少的数据(无论是行数还是更少的列)。或者获得更快的磁盘。或两者。但真正的问题不仅在于写入 200 万行,还在于记录所有这些信息。您可以将 BCP 数据导出,然后以最少的日志记录将其取回。延迟持久性也可能有所帮助。
猜你喜欢
  • 2011-12-24
  • 1970-01-01
  • 2010-11-03
  • 1970-01-01
  • 2021-07-21
  • 2012-10-25
  • 2013-11-12
  • 2016-08-28
  • 2011-03-30
相关资源
最近更新 更多