SQL Server 列存储索引更新/插入存储过程

Posted

技术标签:

【中文标题】SQL Server 列存储索引更新/插入存储过程【英文标题】:SQL Server columnstore index update/insert in stored procedure 【发布时间】:2012-10-29 07:26:04 【问题描述】:

我在测试 sql server 2012 的列存储索引功能时玩得很开心。因为您无法使用此类索引更新/插入表,所以我阅读了一些选项:保留一个单独的表并为每个批量插入使用新分区或禁用索引,执行更新/插入,然后重建索引。

对于我的测试,我选择了后一个选项并最终得到了这个存储过程:

-- Disable the columnstore index.
ALTER INDEX [All_Columns_Columnstore_Index] ON [dbo].[Tick] DISABLE

-- Insert data into tick table from staging table.
insert into Tick
select [Date],
       SymbolID,
       Price
from TickTemporary

-- Delete data from staging table.
delete from TickTemporary

-- Enable (rebuild) the columnstore index.
ALTER INDEX [All_Columns_Columnstore_Index] ON [dbo].[Tick] REBUILD

如果我手动执行这些行,一切正常。但是,如果我运行该过程,我会收到无法在具有列存储索引的表上执行更新/插入的错误。

这是为什么?

更新:

我遵循了我之前接受的答案中的建议,但我仍然得到同样的结果。

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Disable the columnstore index.
EXEC DisableColumnStoreIndex

-- Insert data into tick table from staging table.
insert into Tick
select [Date],
       SymbolID,
       Price
from TickTemporary

-- Delete data from staging table.
delete from TickTemporary

-- Enable (rebuild) the columnstore index.
EXEC RebuildColumnStoreIndex

甚至尝试在存储过程调用周围放置“begin tran”和“commit tran”。

使用动态 sql 之类的:

declare @sql nvarchar(max)
set @sql =
    'insert into Tick
     select [Date],
            SymbolID,
            Price
     from TickTemporary'
exec(@sql)

有效,但实际上,我想在没有动态 sql 的情况下过日子。这种情况下不可以吗?

【问题讨论】:

【参考方案1】:

检查是在编译时完成的,而不是在执行时。将过程分离成自己的,或者使用动态 SQL。

但作为一般性评论,这不是正确的方法。您应该插入具有相同结构的不同表,在此相同表上构建列存储索引,然后使用分区切换将旧表替换为新表:用空表切换旧表,切换新表,丢弃旧数据切换出去。类似于How to Update a table with a Columnstore Index 中描述的过程。由于使用了分区切换,您的表用户的停机时间大大缩短,因为旧表在插入和构建列存储阶段仍然在线且可用。

【讨论】:

是的。我计划在未来使用该策略。但现在这只是我的一个非常小的实验,我没有那么多数据。但我已经阅读了你提到的链接,所以我知道这种方法。当这个简单的事情不起作用时,我就卡住了。 我认为你没有理解这个建议。您的尝试仍然必须编译一个插入到列存储索引中的存储过程,这将触发错误。您必须将 INSERT 分开,以免在列存储索引存在时进行编译,就这么简单,并且没有解决方法。动态 SQL 是一个强制编译在正确时间发生的示例。 抱歉。那我明白了。虽然我认为当您实际执行“CREATE PROCEDURE”或“ALTER PROCEDURE”语句时没有进行相同的检查,这很奇怪。不过谢谢。【参考方案2】:

此编译时执行的解决方案是 Option(recompile)

create  PROCEDURE TEST
AS
BEGIN

ALTER INDEX [All_Columns_Columnstore_Index] ON [dbo].[Tick] DISABLE

-- Insert data into tick table from staging table.

insert into Tick
select [Date],
       SymbolID,
       Price
from TickTemporary  **Option(recompile)**

-- Delete data from staging table.
delete from TickTemporary

-- Enable (rebuild) the columnstore index.
ALTER INDEX [All_Columns_Columnstore_Index] ON [dbo].[Tick] REBUILD

End

【讨论】:

以上是关于SQL Server 列存储索引更新/插入存储过程的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 上插入更新存储过程

如何比较两个表的列并将值插入到基于 SQL Server 中存储过程中的比较的新表中

sql server中批量插入与更新两种解决方案分享(存储过程)

更新表以按分组列显示总计 SQL Server 2008 R2

使用存储过程中查询中项目的索引位置更新列

SQL Server 索引重新创建存储过程慢