您应该将索引放在要更新的SQL表上吗?

时间:2014-10-10 12:14:41

标签: sql sql-server

我们每天晚上都有一张工作台,有超过一百万条记录。 这个程序每晚大约需要3个小时才能完成。在procedure中,我们首先将所有数据插入表中。然后我们对表做了很多更新。

例如:

Update a
Set a.Field1 = b.Field1
From WorkingTable as a JOIN Table2 as b
Where a.ID = b.ID

此时我们没有为WorkingTable分配任何索引或键。如果我们为Index分配了KeysWorkingTable,它会更快地运行吗?

由于

3 个答案:

答案 0 :(得分:1)

要回答这个问题,您首先需要了解密钥和索引在SQL Server中的工作原理。

默认情况下,主键是群集唯一索引。虽然这确实减慢了插入记录的速度,但减速应该是最小的。性能的真正下降通常来自SQL查询中的where子句或导致表扫描的DML语句。如果您在初始创建后更新了足够的记录,那么在id列上添加主键或群集唯一索引将是性能获胜。

确实使用主键或索引的决定归结为这个问题:

  

谁生成" id"?加载数据或数据库的应用程序?

如果加载数据的应用程序生成" id"值,然后在该列上添加聚簇索引就足够了。

CREATE CLUSTERED INDEX IDX_WorkTable_ID 
ON dbo.WorkTable (ID); 

如果数据库正在生成这些值,只需创建" id"列是int类型的主键:

ALTER TABLE [WorkTable] ADD ID INT IDENTITY(1,1);

使用主键,插入,更新和删除仍然非常快。

来自MSDN

  

除了少数例外,每个表都应该有一个聚簇索引。除了提高查询性能外,还可以根据需要重建或重组聚簇索引,以控制表碎片。也可以在视图上创建聚簇索引。

相关:Clustered and Nonclustered Indexes Explained

如果需要更新已编制索引的列的值,则索引可能会拖累性能。对这些列值的每次更新都会导致SQL Server重建该索引。

与任何性能增强一样,请进行测试。证据就在布丁中。

<强>结论

  1. 编写SQL以避免表扫描。
  2. 不要在更新了值的列上创建索引,也不要在where子句中为其他查询或语句创建不需要的列
  3. 避免不必要的连接
  4. 这些是任何SQL查询的基本性能指南。

答案 1 :(得分:0)

它可能运行得更快,但可能没有。索引存在并不能保证它会被使用。

我们假设你的例子中的table2只包含两个记录。那么dbms在WorkingTable.id上使用索引来快速找到两条记录肯定是有意义的。

现在让我们说table2包含的记录数是工作表的10000倍。然后,简单地通过工作表记录进行记录并查找Table2.id的索引可能更有意义。那么你的工作表中不需要索引。

话虽如此:无法保证索引可以加快速度,但也可能。如果它没有,也没有造成任何伤害。正如Luc M在对您的请求的评论中所说的那样:当有必须关注的索引时插入和删除会变慢(但据我了解,此时您已完成插入)。并且更新并选择可以从索引中获利。

所以是的,使用索引(在您的示例的WorkingTable.id上)并查看它们是否有帮助。

答案 2 :(得分:0)

此序列应提高性能(您需要做出准确的时间来确定):

  1. 加载WorkingTable
  2. 为工作表的ID创建索引
  3. 为table2的ID创建索引(如果尚未创建)
  4. 进行更新
  5. 准确测量时间(不要在生产服务器上执行此操作!):<​​/ p>

    CHECKPOINT
    DBCC DROPCLEANBUFFERS
    DBCC FREEPROCCACHE
    SET STATISTICS IO, TIME ON