0

TSql 合并指令由于某种原因变慢了。

我批量合并数据,批量大小等于 10000 条记录,我发现从一个批次到另一个合并需要的时间越来越长。

这是合并指令:

MERGE [dbo].[SResult] AS target
            USING [dbo].[SResultTemp] AS source 
            ON (target.QSId = source.QSId 
                and target.ResultId = source.ResultId 
                and target.EngineId = source.EngineId)  
            WHEN NOT MATCHED THEN INSERT 
                (QSId, ResultId, EngineId, Position) 
            values 
                (source.QSId, source.ResultId, source.EngineId, source.Position);

像这样声明的源表

    CREATE TABLE [dbo].[SResultTemp](
        [QSId] int not null,
        [ResultId] int not null,
        [EngineId] int not null,
        [Position] int not null,
        CONSTRAINT [PK_SResultTemp] PRIMARY KEY CLUSTERED(
            [QSId], [ResultId], [EngineId], [Position] ASC
        )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
        ) ON [PRIMARY]

目标是相同的,但它具有附加字段 SResultId 作为主键和另一组索引:

PK_SResult - 主要

IX_SResult_QSId_ResultId - 非唯一、非集群

IX_SResult_EngineId - 非唯一、非集群

UX_SResult_EngineId_QSId_Position - 唯一,非集群

这是我在日志中看到的:

    Results Upload: SResult took 00:00:01.0008344 
    Results Upload: SResult took 00:00:18.1046734
    Results Upload: SResult took 00:00:17.9797846
    Results Upload: SResult took 00:00:27.7828817
    Results Upload: SResult took 00:01:30.4140091
    Results Upload: SResult took 00:03:17.6433416
    Results Upload: SResult took 00:03:21.3761251
    Results Upload: SResult took 00:06:07.2555342
    Results Upload: SResult took 00:06:56.2423653
    Results Upload: SResult took 00:06:57.1729179
    Results Upload: SResult took 00:07:09.7221083

此外,我使用多个表,因此对于其他表没有这样的规律性。任何人都可以帮忙吗?

谢谢!

4

3 回答 3

1

当然,对于具有四个字段的集群 PK,您还期望什么?在合并期间,您不断地重新排序表中的所有记录。

于 2013-08-21T13:59:00.117 回答
1

随着索引片段插入速度的降低。
正如你所见,它会迅速退化。
如果您可以按PK的顺序插入,那么这将减少碎片。
填充索引将减慢碎片。
您可以删除所有非聚集索引然后在插入完成后重建吗?

SResultId 是身份吗?

为什么要设计索引?
您有一个与 SResultTemp 上的 PK 不同的唯一约束。

索引加快了选择,但它们减慢了插入和更新。
连接上的索引会有所帮助,但现在该索引已被拆分。

我的建议是将其分解为唯一性和测试所需的索引。

于 2013-08-21T14:01:02.307 回答
0

有两个问题:

  1. 随着越来越多的行添加,增加索引和由此产生的维护工作
  2. 附加条款

    ON (target.QSId = source.QSId 
        and target.ResultId = source.ResultId 
        and target.EngineId = source.EngineId) 
    

随着越来越多的行需要比较,导致在目标中检查的需求增加。

去掉索引会极大地减慢 ON 子句的检查。我们在这里有利益冲突。

于 2013-08-21T14:05:43.637 回答