sai*_*ram 6 sql-server-2008 sql-server t-sql
我有大约 1250000 条记录和 80 列
表结构
CREATE TABLE [dbo].[Table] (
[Column1] [int] IDENTITY(1, 1) NOT FOR REPLICATION NOT NULL, [Column2] [int] NULL, [Column3] [int] NULL,
[Column4] [int] NULL, [Column5] [int] NULL, [Column6] [int] NULL, [Column7] [int] NULL, [Column8] [int] NULL,
[Column9] [int] NULL, [Column10] [varchar](20) NULL, [Column11] [datetime] NULL, [Column12] [int] NULL,
[Column13] [money] NULL, [Column14] [money] NULL, [Column15] [varchar](40) NULL, [Column16] [int] NULL,
[Column17] [int] NULL, [Column18] [varchar](20) NULL, [Column19] [varchar](50) NULL, [Column20] [int] NULL,
[Column21] [int] NULL, [Column22] [int] NULL, [Column23] [int] NULL, [Column24] [int] NULL,
[Column25Date] [datetime] NULL, [Column26] [int] NULL, [Column27] [int] NULL, [Column28] [int] NULL,
[Column29] [int] NULL, [Column30] [int] NULL, [Column75] [varchar](50) NULL, [Column31] [int] NULL,
[Column32] [varchar](15) NULL, [Column33] [int] NULL, [Column34] [money] NULL,
[Column35] [dbo].[T_Boolean2] NOT NULL, [Column36] [money] NULL, [Column37] [money] NULL,
[Column38] [int] NULL, [Column39] [int] NULL, [Column40] [varchar](255) NULL, [Column41PrintDate] [datetime] NULL,
[Column42PostDate] [datetime] NULL, [Column43FirstName] [varchar](30) NULL, [Column44LastName] [varchar](30) NULL,
[Column45Email] [varchar](50) NULL, [Column46PrimaryPhone] [varchar](10) NULL,
[Column47SecondaryPhone] [varchar](10) NULL, [Column48PrimaryPhoneType] [smallint] NULL,
[Column49SecondaryPhoneType] [smallint] NULL, [Column50PrimaryPhoneType] [smallint] NULL,
[Column51SecondaryPhoneType] [smallint] NULL, [Column52EndDate] [datetime] NULL,
[Column53] [dbo].[T_Boolean2] NOT NULL, [Column54] [int] NULL, [InsertTimeStamp] [datetime] NOT NULL,
[UpdateTimeStamp] [datetime] NULL, [Column55ID] [int] NULL, [Column56] [int] NULL, [Column57] [int] NULL,
[Column58] [int] NULL, [Column59] [money] NULL, [Column60] [money] NULL, [Column61] [money] NOT NULL,
[Column62] [money] NOT NULL, [Column63] [varchar](30) NULL, [Column64] [varchar](30) NULL,
[Column65] [varchar](10) NULL, [Column66] [varchar](6) NULL, [Column67] [varchar](10) NULL,
[Column68] [varchar](35) NULL, [Column69Date] [datetime] NULL, [Column70Date] [datetime] NULL,
[Column71Date] [datetime] NULL, [Column72] [varchar](255) NULL, [Column73PIN] [varchar](6) NULL,
[Column74Date] [datetime] NULL, [Column76Date] [datetime] NULL,
CONSTRAINT [XPKColumn1] PRIMARY KEY CLUSTERED (
[Column1] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
它有 2 个更新触发器也可以执行后台计算,当状态改变和其他一些条件时,它将更新同一个表
当我更新一个是它的列,条件正常时,它运行了 1 个多小时,但仍然无法更新记录,所以我被迫终止该语句
Update Table Column5 = 12345 where Column5 = 6789
Run Code Online (Sandbox Code Playgroud)
它必须更新大约 35000 条记录
表确实有正确的索引与此列,我手动更新表的统计信息,但仍然需要太多时间来更新
表有大约 10 个索引
然后我尝试分 2 批更新它更新但花了很长时间
我试图更新同一个表的其他列,更新需要几秒钟
Update Table Column3 = 6789 where Column3 = 12345
Run Code Online (Sandbox Code Playgroud)
我如何快速提高更新语句查询速度并使用上述简单逻辑
请提出任何解决方案,
提前致谢
如果没有看到触发器的代码,很难确切地说出导致它的原因,但我敢打赌,误用 INSERTED 和 DELETED 虚拟表是罪魁祸首。
INSERTED 和 DELETED 的问题在于它们没有索引。如果您将它们直接连接回基表(或相互连接),则最终可能会出现非常糟糕的性能。
您通常可以通过将两者加载到临时表并为您将加入它们的索引(通常在主键上)创建索引来缓解这种情况。
SELECT *
INTO #i
FROM INSERTED
CREATE CLUSTERED INDEX CX_i ON #i (primary_key)
SELECT *
INTO #d
FROM DELETED
CREATE CLUSTERED INDEX CX_d ON #d (primary_key)
Run Code Online (Sandbox Code Playgroud)
反正就是这样。然后只使用您的临时表,不要触摸 INSERTED 和 DELETED。
请注意,每个会话的临时表名称必须是唯一的。如果您有多个触发器级联,则它们需要使用唯一的表名。如果这成为一个问题,您可能希望改用表变量,因为它们的范围仅限于它们正在运行的触发器/过程,没有名称冲突的风险。(但是,索引表变量的唯一方法是在DECLARE语句中声明聚集主键。)
您可以通过以较小的组更新表来提高更新操作的性能。
参见示例:
SET rowcount 10000
Update Table
Column3 = 6789
where Column3 = 12345
while @@rowcount>0
Update Table
Column3 = 6789
where Column3 = 12345
END
SET rowcount 0
Run Code Online (Sandbox Code Playgroud)
上面的代码一次更新 10000 行,循环继续直到 @@rowcount 的值等于 0。这可以确保表不被锁定。
在 SQL Server 中更新大型表时的最佳实践
另一个补充- 这可能有点复杂,当您拥有大表时,最好按特定字段进行分区,然后将这些分区分布在多个磁盘上。
| 归档时间: |
|
| 查看次数: |
10787 次 |
| 最近记录: |