【发布时间】:2017-04-27 01:12:45
【问题描述】:
我有一张表,带有 DML 的 IDMAP:
CREATE TABLE tempdb2.dbo.idmaptemp (
OldId varchar(20),
CV_ModStamp datetimeoffset,
NewId varchar(20),
RestoreComplete bit,
RestoreErrorMessage varchar(1000),
OperationType varchar(20)
)
正如它所定义的,它已经包含了一组大约 (100 万) 的预定义行。还原操作完成后,我必须更新表上的 NewId、RestoreComplete、RestoreErrorMessage。 声明是:
update tempdb2.dbo.IdMaptemp set NewId = 'xxx', RestoreComplete = 'false', RestoreErrorMessage = 'error' where OldId = 'ABC';
Java 应用程序在内存中有大约一百万个值,并且必须使用上述语句更新这些值。数据库设置为关闭自动提交,并随批次(批次大小 500)而变化。
我在使用 OldId 字段进行索引时尝试了两个选项:
聚集索引 - 执行计划列为聚集索引更新(100% 成本)。发生这种情况是因为叶子是正在更新的行并且会触发索引更新。我在吗?
非聚集索引 - 执行计划列为更新 (75%) 和查找 (25%)。
在对数据库表进行大规模更新时,是否可以实现其他任何加速?该表无法清除并重新插入,因为还有其他行不受更新影响。每批 500 行样本的聚集索引需要大约 7 个小时来更新。
我应该选择非聚集索引选项吗?
【问题讨论】:
-
百分比是没有意义的,它们只是说明成本在计划中是如何分配的,在计划之外没有任何价值。
-
@Mark Rotteveel 可以找到执行计划的哪个阶段需要时间的任何信息?
-
如果您正在对性能进行故障排除,也许您可以将更新从 Java 中移出并放入 SQL 脚本中。您是否正在针对此表运行 100 万条单独的更新语句?如果是这样,您可能会发现很大一部分性能问题是由于单个更新语句而不是任何特定索引造成的。如果您可以重构您的流程以在数据库中执行所有这些操作,它会更快。例如,将一百万个值批量加载到另一个表中,然后在一批中执行数据库更新。
-
@Nick.McDermaid 我知道在数据库层做的方法更快。来自应用程序开发人员的观点,如果有几个表在更新字段中有所不同,我应该为每个表编写代码吗?尽管让数据库来做跑腿工作似乎是合适的,但这似乎并不可靠。希望有一个实用程序或驱动程序可以使用临时表方法处理大量更新!
-
我看不出为 Java 应用程序或数据库中的每个表编写代码之间的区别。也许您的 Java 应用程序中有一些动态代码。在数据库中编写非动态代码可以实现某些性能改进。无论如何,真正的问题是你的 Java 应用程序中的这些百万数据点来自哪里?它们是来自另一个数据库还是可以在数据库中生成?如果您的数据是从 DB>Java>DB 往返,那么在我看来,您有一个提高性能的好机会
标签: sql sql-server indexing