ado*_*lot 30 performance sql-server-2005 sql-server application-design fragmentation
我正在做一个项目,我需要每天在一张表中更改大约 36K 条记录。我想知道什么会表现得更好:
对我来说,删除所有行并插入新行会更容易,但如果这会使表和索引碎片化并影响性能,那么我更愿意在可能的情况下进行更新并仅在必要时删除/插入。
这将是一项夜间服务,我不希望提高流程本身的速度。我更关心对这个表的查询性能,我已经有 8900 万条记录,以及这个每晚的过程将如何影响它。
对于这个夜间流程,我应该删除/插入记录还是应该更新现有记录(在可能的情况下)?
Dha*_*DK' 13
这实际上取决于有多少数据正在发生变化。假设这个表有 20 列。而且您还有 5 个索引 - 每个索引都在一个差异上。柱子。
现在,如果所有 20 列中的值都在更改或即使 5 列中的数据发生更改并且这 5 列都已编入索引,那么“删除和插入”可能会更好。但是,如果只有 2 列正在更改,并且可以说它们不是任何非聚集索引的一部分,那么您最好“更新”记录,因为在这种情况下,只会更新聚集索引(并且索引不必更新)更新)。
在进一步的研究中,我确实发现我的上述评论有点多余,因为 SQL Server 内部有 2 个单独的机制来执行更新。- “就地更新”(即通过将列值更改为原始行中的新值)或作为“非就地更新”(删除后跟插入)。
就地更新是规则,并在可能的情况下执行。此处,行在同一范围内完全位于同一页面上的同一位置。仅更改受影响的字节。tlog 只有一条记录(假设没有更新触发器)。如果正在更新堆(并且页面上有足够的空间),则会就地进行更新。如果集群键发生变化但行根本不需要移动,更新也会就地发生。
例如:如果你有一个关于姓氏的聚集索引并且你有以下名字:Able、Baker、Charlie 现在你想将 Baker 更新为 Becker。无需移动任何行。所以这可以就地进行。然而,如果您必须将 Able 更新为 Kumar,则必须移动行(即使它们位于同一页面上)。在这种情况下,SQL Server 将执行 DELETE,然后执行 INSERT。
考虑到上述情况,我建议您进行常规 UPDATE 并让 SQL Server 找出如何在内部执行此操作的最佳方法。
有关“更新”内部结构或任何 SQL Server 相关内部结构的更多详细信息,请查看 Kalen Delaney、Paul Randal 等人的书 - SQL Server 2008 Internals。
您是否研究过SQL 2008 中的MERGE命令?这是一个基本示例:
merge YourBigTable ybt
using (select distinct (RecordID) from YourOtherTable) yot
on yot.Recordid = YBT.RecordID
when NOT matched by target
then insert (RecordID)
values (yot.DeviceID) ;
Run Code Online (Sandbox Code Playgroud)
这基本上是一个“UPSERT”命令。如果存在则更新,如果不存在则插入。非常快,非常酷的命令。
小智 6
但是,我自己在一个有 3000 万(3 千万)条记录的表上检查了删除和插入 vs 更新。该表有一个聚集唯一复合键和 3 个非聚集键。对于删除和插入,需要 9 分钟。更新需要 55 分钟。每行中只有一列被更新。
所以,我请你们不要猜测。当处理包含许多列和大量数据的大表时,方程会发生变化。
更新没有那么快。实现快速插入的诀窍是在插入数据时禁用索引。
考虑使用这个:
-- disable indexes
ALTER INDEX [index_name] ON dbo.import_table DISABLE
-- ... disable more indexes
-- don't use delete if you don't care about minimal logging. truncate is faster
TRUNCATE TABLE dbo.import_table
-- just insert the new rows
INSERT dbo.import_table
SELECT
*
FROM
dbo.source_table
-- rebuild indexes
ALTER INDEX [index_name] ON dbo.import_table REBUILD
-- ... rebuild more indexes
Run Code Online (Sandbox Code Playgroud)
更快的是在 db 选项中关闭自动统计更新。如果表发生重大变化,您应该运行:
UPDATE STATISTICS dbo.import_table
Run Code Online (Sandbox Code Playgroud)
或者
EXEC sp_updatestats
Run Code Online (Sandbox Code Playgroud)
作为定期工作(每天,每周,取决于数据库大小)以保持最新统计数据。需要注意的是在表为空时更新统计信息。如果您在再次填充表后不运行它,那将会搞砸统计数据。
| 归档时间: |
|
| 查看次数: |
55196 次 |
| 最近记录: |