【问题标题】:INSERT query runs slowly when there is a non-clustered column store index当存在非聚集列存储索引时,INSERT 查询运行缓慢
【发布时间】:2018-08-07 21:35:49
【问题描述】:

我的本​​地主机数据库(16 CPU,124 GB RAM)中有一个大测试表,它具有非聚集列存储索引。每天我都会在这个表中插入 1000 万行。我发现我的系统运行很慢,没有结束。

我看到 2 个查询并行运行而没有结束,它们使系统非常慢:

查询 1:

INSERT INTO TABLE ABC

查询 2:

ALTER NONCLUSTERED COLUMN STORED INDEX TABE ABC.

我的问题:

  1. 插入非聚集列存储索引非常慢,因为它会同时插入新记录并更改索引。对吗?

  2. 是否需要在 INSERT 之前禁用 INDEX,在 INSERT 之后启用 INDEX 以提高性能?

我使用 SQL Server 2016,此版本允许我们插入、更新具有非聚集列存储索引的表。

谢谢

【问题讨论】:

  • INSERT 语句不完整,ALTER 语句也不完整(其中也包含语法错误)。你能提供更完整的陈述吗?
  • 我只能提供测试语句,完整的语句很长。否则,这是一个示例,它显示了一个插入到具有非聚集列存储索引的表的示例

标签: sql-server insert sql-server-2016


【解决方案1】:

那些不能并行运行,因为根据documentation:

在表上创建非聚集列存储索引后,您无法直接修改该表中的数据。带有 INSERT、UPDATE、DELETE 或 MERGE 的查询将失败并返回错误消息。要添加或修改表中的数据,您可以执行以下操作之一:

  • 禁用列存储索引。然后,您可以更新表中的数据。如果禁用列存储索引,则可以在完成数据更新后重建列存储索引。例如:

  • 删除列存储索引,更新表,然后使用 CREATE COLUMNSTORE INDEX 重新创建列存储索引。例如:

示例

ALTER INDEX mycolumnstoreindex ON mytable DISABLE;  
-- update mytable --  
ALTER INDEX mycolumnstoreindex on mytable REBUILD  


DROP INDEX mycolumnstoreindex ON mytable  
-- update mytable --  
CREATE NONCLUSTERED COLUMNSTORE INDEX mycolumnstoreindex ON mytable;  

所以是的,您需要在INSERT 和INSERT 之后的DISABLE 和REBUILD,或 DROP 然后在INSERT 和CREATE 之前索引在INSERT 之后再次出现。我猜 运行缓慢并且永远不会完成 是与该索引分开的阻塞问题。

如果问题更笼统,对于普通的NONCLUSTERED INDEX,当您尝试插入大量记录(例如,在您的情况下为 1000 万条)时,删除并重新创建索引可能是有益的,因为

  • 索引会减慢插入、更新和删除(页面拆分、插入/更新多个索引等)的速度
  • 插入这么多记录可能会导致大量碎片

【讨论】:

  • 感谢 scsimon,在 sql server 2014 中我们不能 INSERT,UPDATE 具有非聚集列存储索引的表,但在 sql server 2016 版本中,我们可以 UPDATE 和 INSERT 这个表。跨度>
  • @phalondon 你没有标记 2016,所以我没有假设这一点。最后的项目符号仍然适用,禁用和重建会更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 2018-04-26
  • 1970-01-01
  • 2011-10-03
相关资源
最近更新 更多