经常重新填充大表索引

Frequently repopulated large tables indexes

我有一组数据(超过 200 万行)需要每隔几分钟重新填充一次。数据也必须在那段时间访问,所以我们有这个解决方案:

当视图指向 Table_First 时,我们:

您认为这是一个好的设计,还是我们可以做得更好?

我在想,每次重建索引后,统计信息都会丢失,并且每个从 TableView 中选择数据的查询都会被重新编译。我应该担心吗?

另一个是重建实际上有时比数据插入花费更多的时间。

作为替代方案,我们可以将行插入临时 table(或持久性 table),然后使用 MERGE 与 INSERT、UPDATE 和 DELETE 更新数据。

table 看起来像这样:

CREATE TABLE [dbo].[Table_First](
[GroupId] [int] NOT NULL,
[ItemId] [int] NOT NULL,
[SKU] [nvarchar](255) NOT NULL,
[PropertyId] [int] NOT NULL,
[StringValue] [nvarchar](500) NULL,
[DecimalValue] [float] NULL,
[PropertyValueId] [int] NULL) ON [PRIMARY]

CREATE CLUSTERED INDEX [IX_Index1] ON [dbo].[Table_First]
(
    [GroupId] ASC,
    [PropertyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

CREATE NONCLUSTERED INDEX [IX_Index2] ON [dbo].[Table_First]
(
    [SKU] ASC,
    [PropertyId] ASC
)
INCLUDE ([PropertyValueId]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

不幸的是,table 中的数据不是唯一的。

您的解决方案可能是可行的,但它取决于许多方面,例如您的阅读量。这里的主要瓶颈是:

  • Sch-M 锁由 ALTER VIEW 语句放置在视图上,在此期间没有其他会话可以访问它。如果你能忍受,那很好;
  • 更改视图将导致重新编译所有使用它的查询。如果你的查询很少,还可以接受。

但是,还有其他选择。

您可以在 table 所在的数据库中启用读取提交快照隔离 (RCSI)。之后,上述所有内容将由 SQL 服务器本身在幕后执行。

您可以使用 table 分区来进行投标。通过切换新部分和旧部分,它与您的原始计划基本相同,尽管可能没有 table 差异。但是,并非每个版本的 SQL 服务器都支持 table 分区。

我自己并没有玩太多,但是从SQL Server 2014开始,有一个很好的特性,即内存tables。它们减少了锁争用和磁盘占用空间,因此可能值得研究。