2012-01-04 125 views
1

我有一張表,我將用昂貴的計算值(使用來自不可變XML列的xquery)填充值。爲了加速部署到生產,我已經在測試服務器上預先計算了值,並將其保存到帶有BCP的文件中。按順序運行時SQL查詢速度慢,但在單獨運行時速度很快

我的腳本如下

-- 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包含20萬行和XmlColumn的數據是相當大的,總表的大小〜3GB
  • foo表得到130萬行

有什麼事情可能會有所作爲?
管理工作室關閉了隱式交易。就我所能理解的,每條陳述都會在自己的交易中運行。

更新:
如果我先選擇並運行腳本,直到-- rerun from here after the break,然後選擇並運行剛剛過去的查詢,它仍然是緩慢的,直到我取消執行,然後再試一次。這至少排除了與腳本中的前一代碼「一起」運行的任何效果,並歸結爲相同的查詢在第一次執行時速度慢,在第二次時速度很快(在所有其他條件相同的情況下運行)。

+0

你可以看到在執行計劃的任何差異?最後一個陳述需要4個小時,你可以看看估計的計劃,而不是實際的(至少是一開始)。 – 2012-01-04 08:12:49

+0

「如果我在幾分鐘後取消查詢執行並僅選擇最後一個查詢並單獨運行,它將在5秒內完成。「 - 你是否自己運行select,將結果插入空foo中或將結果插入到foo中?foo獲取大部分來自BCP進程的130M行還是來自OtherTable的插入? – 2012-01-04 08:49:41

+0

@MarkBannister ,我正在運行帶有填充表的select,我只是從按下cancel的地方繼續使用同一個腳本,所有的1.3M行都來自批量插入(這就是'(0 row(s)affected) '表示)。 – 2012-01-04 09:08:45

回答

0

不知道究竟爲什麼它幫助,但我重寫了最後一個查詢到left outer join,而不是突然執行降至15毫秒。

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 
INNER JOIN FOO f ON o.ID = f.ID 
    CROSS APPLY o.XmlColumn.nodes('(item/.../salesorder/)') h(n) 
WHERE f.ID = null 
) as E 
GROUP BY e.ID 
2
+0

我用http://www.fulltablescan.com/index.php?/archives/149-查看 - 執行 - 程序 - 運行 - 運行 - 查詢 - SQL - 服務器.html得到緩慢運行查詢的執行計劃,但據我所見,它在第二次運行查詢時使用相同的執行計劃。不幸的是,我無法得到每個部分的執行計數(我對數字感興趣除非我等待4個小時,我會盡量讓查詢在一夜之間運行,以獲得完整的執行計劃 – 2012-01-04 09:19:58

+0

此外,爲什麼執行計劃會在來自Management Studio的兩個相同調用之間發生變化,而兩者之間沒有其他活動? – 2012-01-04 10:04:07

+0

'執行計劃爲什麼會在':stats – 2012-01-04 15:18:29

1

難道有一定的相關統計是完全錯誤的新創建的Foo表?如果SQL Server在首次運行查詢時自動更新統計信息,則第二次運行將根據最新的統計信息創建其執行計劃。

如果你查看統計信息批量插入(與STATS_DATE功能)之後,然後不得不取消了長時間運行的查詢後,再次檢查了嗎?即使查詢被取消,統計數據是否得到更新?

在這種情況下,Foo之後批量插入可以幫助一個UPDATE STATISTICS

+0

之間變化?FOO表的PK的統計日期在查詢執行後爲空。聽起來像是一個可能的修復。但是,我設法通過將查詢重寫爲'LEFT OUTER JOIN'來獲得合理的執行時間。 – 2012-01-04 11:55:13

相關問題