【发布时间】:2012-01-04 07:21:39
【问题描述】:
我有一个表,我将使用来自昂贵计算的值(使用来自不可变 XML 列的 xquery)填充该表。为了加快部署到生产的速度,我在测试服务器上预先计算了值并使用 BCP 保存到文件中。
我的脚本如下
-- Lots of other work, including modifying OtherTable
CREATE TABLE FOO (...)
GO
BULK INSERT FOO
FROM 'C:\foo.dat';
GO
-- rerun from here after the break
INSERT INTO FOO
(ID, TotalQuantity)
SELECT
e.ID,
SUM(e.Quantity) as TotalQuantity
FROM (select
o.ID,
h.n.value('TotalQuantity[1]/.', 'int') as TotalQuantity
FROM dbo.OtherTable o
CROSS APPLY XmlColumn.nodes('(item/.../salesorder/)') h(n)
WHERE o.ID NOT IN (SELECT DISTINCT ID FROM FOO)
) as E
GROUP BY e.ID
当我在 management studio 中运行脚本时,前两个语句在几秒钟内完成,但最后一个语句需要 4 小时才能完成。由于我的 foo.dat 是计算管理工作室报告 (0 row(s) affected),因此没有向 OtherTable 添加任何行。
如果我在几分钟后取消查询执行并仅选择最后一个查询并单独运行它,它将在 5 秒内完成。
值得注意的事实:
- OtherTable 包含 200k 行,XmlColumn 中的数据非常大,总表大小 ~3GB
- FOO 表有 130 万行
什么可能会有所作为?
Management Studio 已关闭隐式事务。据我所知,每条语句都会在自己的事务中运行。
更新:
如果我首先选择并运行脚本直到-- rerun from here after the break,然后选择并运行最后一个查询,它仍然很慢,直到我取消执行并重试。这至少排除了与脚本中的先前代码“一起”运行的任何影响,并归结为相同的查询在第一次执行时很慢,在第二次执行时很快(在所有其他条件相同的情况下运行)。
【问题讨论】:
-
你能看出执行计划有什么不同吗?由于最后一条语句需要 4 小时,您可以查看估计计划而不是实际计划(至少在开始时)。
-
“如果我在几分钟后取消查询执行并只选择最后一个查询并单独运行它,它将在 5 秒内完成。” - 您是自行运行选择,将结果插入到空的 foo 中,还是将结果插入到已填充的 foo 中? foo 是否主要从 BCP 进程或从 OtherTable 的插入中获得 130 万行?
-
@MarkBannister,我正在运行选择并填充表格。我只是从按下取消的位置继续执行相同的脚本。所有 130 万行都来自批量插入。 (这就是
(0 row(s) affected)所表示的)。
标签: sql sql-server