如何重新索引审计表?非聚类的主键,聚类覆盖索引,GUID



使用SQL Server 2016标准。我有一个现有的AuditLog表,在bigint列(生成的C#侧(上带有PK和一个额外的索引。

CREATE TABLE [dbo].[AuditLog]
(
    [Id] [bigint] NOT NULL,
    [ChangeTime] [datetime] NOT NULL,
    [User] [varchar](100) NOT NULL,
    [RootId] [bigint] NOT NULL,
    [EntityId] [bigint] NOT NULL,
    [EntityName] [varchar](100) NOT NULL,
    [Operation] [varchar](100) NOT NULL,
    [OldValue] [varchar](max) NULL,
    [NewValue] [varchar](max) NULL
)
ALTER TABLE [dbo].[AuditLog] 
    ADD CONSTRAINT [PK_AuditLog] 
        PRIMARY KEY CLUSTERED ([Id] ASC)
CREATE NONCLUSTERED INDEX [IX_AuditLog_RootId] 
    ON [dbo].[AuditLog] ([RootId] ASC)

使用当前的105,000,000行,尺寸为(使用used_page_count * 8k每页(:

  • pk_auditlog:11,535,112 kb
  • ix_auditlog_rootid:2,370,480 kb

我现在必须从SQL中的存储过程中在此表中创建行,而不再仅在C#中创建行,因此我需要一个可以生成SQL端(以及C#Still(的主键。我认为我的选择是int identityguid(默认为NEWSEQUENTIALID(。

由于我的大多数用法都包括日期和按日期订购,因此我正在考虑将其聚类。听起来对吗?

,由于我几乎总是按RootIdUser过滤,因此我考虑将它们包括在我的索引中。在集群索引中包括其他列是一个好主意吗?还是应该在单独的覆盖索引中?

每个索引都需要唯一识别行,因此即使我不指定我的群集索引也将包含主键。因此,使用Guid作为PK似乎是存储的坏主意,尤其是1亿行。所以我正在使用bigint

由于我的pk不被限制(因此没有按该顺序存储(,因此SQL Server如何奏效下一个身份?我怀疑它可以分类PK以找到最大值。在非集群列上使用身份是一个坏主意吗?

另外,我想我可以使用精度3(存储7个字节(而不是datetime(8字节(的datetime2来保持相同的精度,但要节省一些空间(甚至是Precision 4来提高同一存储的精度(?

所以我正在考虑这样做:

CREATE TABLE dbo.AuditLog
(
    Id bigint NOT NULL IDENTITY (1, 1),
    ChangeTime datetime2(4) NOT NULL...

ALTER TABLE AuditLog   
    ADD CONSTRAINT [PK_AuditLog] 
        PRIMARY KEY NONCLUSTERED (Id)
CREATE CLUSTERED INDEX CIX_AuditLog_ChangetimeRootUser 
    ON AuditLog(Changetime, RootId, [User])

脚注

这就是使用表的使用方式:

  • 没有外键或从此表中。

  • 插入重量(用户实体字段的任何添加/编辑/删除插入新的AuditLog行,在工作时间不断插入,必须很快(

  • 偶尔读取(用户检查什么或谁更改了某些东西,即每天几次阅读AuditLog,很高兴不要等待返回查询的年龄(

  • 插入一旦插入的审计行永远不会更新或删除。

典型的过滤器和订单:

  • 仅按日期过滤
  • 按日期和用户过滤
  • 按日期和objectid进行过滤
  • 按日期和用户和objectid进行过滤
  • 仅通过objectid过滤
  • 几乎总是按反向日期进行排序,首先显示最新的更改。
  • 经常使用"偏移x行"one_answers"仅获取下一个x行"
  • 和一个特定用例,相当于使用某个子句选择PK的子集,然后使用PK在主表上自我加入以检索列值

ps:我很清楚该过程及其将要花费的时间,创建临时新表格,在块中复制数据,创建索引等...

由于我的大多数用法都包括日期和按日期订购,所以我正在考虑将其聚类。听起来吗?

没有这样做并评估结果没有办法知道。

在群集索引中包括其他列是一个好主意?

您不能在群集索引中包含列,因为这没什么意义。群集索引最终是表。您在NC索引中包含列,以避免其他查找以访问行的其他列。

SQL Server如何奏效下一个身份?

坦率地说,不用担心。引擎在表级别管理身份 - 它无需参考任何特定行即可确定下一个值。

另外,我想我可以将dateTime2与精度3(存储7个字节(而不是dateTime(8个字节(保持相同的精度,但要保留一点空间(或什至Precision 4来提高同一存储的精度无论如何(?

不要障碍您的数据只是为了节省每个行的单个字节。根据您的要求选择正确的数据类型。存储价格便宜。缺乏精度是永远的。

此外,您的脚注尚不清楚。您可以参考用户实体字段的添加/更新/删除(对于那些不熟悉您的模式的人来说是毫无意义的术语(,并且也"从未更新或删除"。这似乎是一个矛盾,可能是或可能不相关的。

和最终评论。变化涉及风险。如果您当前的架构足够,则 SAFEST 方法是简单地用ID列作为身份重新创建表(并且其他所有内容保持不变(。

相关内容

  • 没有找到相关文章

最新更新