我有一个合并声明,如下所示
MERGE DESTINATION AS DST
USING ( SELECT <Some_Columns> FROM TABLEA WITH(NOLOCK) INNER JOIN TableB .....
) AS SRC
ON(
<some conditions>
)
WHEN MATCHED THEN
UPDATE SET column1 = src.column1
...............
,Modified_By = @PackageName
,Modified_Date = GETDATE()
WHEN NOT MATCHED THEN
INSERT (<Some_Columns>)
VALUES(<Some_Columns>)
OUTPUT
$action, inserted.key'inserted'
INTO @tableVar
;
对于第一组记录(大约300,000),它运行良好,只需30秒即可执行。 但是对于第二组记录(大约300,000),它需要一个多小时。
两天前我已经加载了50套这样的设备,同样的查询工作速度很快,但是从今天起它很慢。我不知道出了什么问题。
注意:查询
SELECT FROM TABLEA WITH(NOLOCK)INNER JOIN TableB .....
所有场景都需要20秒。
答案 0 :(得分:4)
虽然MERGE
语法更好,并且似乎承诺更好的原子性和没有竞争条件(but doesn't, unless you add HOLDLOCK
, as this Dan Guzman post demonstrates),但我仍然认为最好挂起旧式的独立插入/更新方法。主要原因不是语法难以学习(它是什么),或者难以解决并发问题(它不是),而是有几个未解决的错误 - 即使在SQL中也是如此Server 2012仍然 - 涉及此操作。 I point a dozen of them out in this post that talks about yet another MERGE
bug that has been fixed recently。我也是go into more detail in a cautionary tip posted here。
正如我在评论中所说的那样,我不想发出天空正在下降的警报,但我真的不感兴趣转换到MERGE
直到有远活动错误减少。因此,我建议暂时坚持使用老式的UPSERT
,即使您使用的实际语法可能不是您反正遇到的性能问题的根源。
UPDATE dest SET column1 = src.column1
FROM dbo.DestinationTable AS dest
INNER JOIN (some join) AS src
ON (some condition);
INSERT dest(...) SELECT cols
FROM (some join) AS src
WHERE NOT EXISTS
(
SELECT 1 FROM dbo.DestinationTable
WHERE key = src.key
);
对于性能问题,您希望查看会话的等待(SQL Sentry's Plan Explorer PRO *可以为您提供帮助,为您启动扩展事件会话),或者查询正在运行时,blocking_session_id
中的wait_type_desc
和sys.dm_exec_requests
非常至少。
*免责声明:我为SQL Sentry工作。