繁体   English   中英

是否应将索引放在要更新的SQL表上?

[英]Should you put Indexes on a SQL Table that you are updating?

我们有一个每晚都会建立的工作表,记录超过一百万。 每晚大约需要3个小时来完成此过程。 在此procedure我们首先将所有数据插入表中。 然后,我们对该表进行了大量更新。

例如:

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

此时,我们没有任何分配给WorkingTable索引或键。 将运行速度更快,如果我们没有指定一个IndexKeysWorkingTable

谢谢

要回答这个问题,您首先需要知道键和索引在SQL Server中是如何工作的。

默认情况下,主键是聚集的唯一索引。 尽管这样做确实会减慢插入记录的速度,但减慢速度应该很小。 性能的真正下降通常来自导致表扫描的SQL查询或DML语句中的where子句。 如果您在初始创建后更新了足够的记录,那么在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

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

相关: 解释聚集索引和非聚集索引

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

与任何性能增强一样,对其进行测试。 证明在布丁里。

结论

  1. 编写您的SQL以避免表扫描。
  2. 不要在更新了值的列上以及在其他查询或语句的where子句中不需要的列上创建索引
  3. 避免不必要的联接

这些是任何SQL查询的基本性能准则。

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

假设您的示例中的table2仅包含两个记录。 然后,对于dbms,使用WorkingTable.id上的索引来快速查找两条记录绝对是有意义的。

现在,假设table2包含的记录是工作表的10000倍。 然后,更简单地遍历工作表记录进行记录并查找Table2.id的索引可能更有意义。 这样就无需在工作表中建立索引。

话虽这么说:不能保证索引可以加快速度,但是可以。 如果没有,也不会造成任何伤害。 正如Luc M在对您的请求的评论中所说的那样:当有一些索引需要注意时,insert和delete会变慢(但是据我所知,这时您已经完成了插入操作)。 更新和选择可以从索引中受益。

因此,可以的,使用索引(在您的示例中为WorkingTable.id),看看它们是否有帮助。

此序列应提高性能(您需要进行准确的计时以确定):

  1. 加载工作表
  2. 在ID上为工作表创建索引
  3. 在table2的ID上创建索引(如果尚未创建)
  4. 做你的更新

为了准确地测量时间(不要在生产服务器上执行此操作!):

CHECKPOINT
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
SET STATISTICS IO, TIME ON

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM