使用SQL Server 2016 Standard。我有一个现有的AuditLog
表,在bigint
列上有一个PK(生成的C#侧)和一个附加索引。
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):
我现在必须从SQL中的存储过程创建此表中的行,而不再是c#中的行,所以我需要一个可以生成SQL端的主键(和C#仍然)。我认为我的选择是int identity
和guid
(默认为NEWSEQUENTIALID
)。
由于我的大部分用法都包括按日期排序的日期和顺序,因此我正在考虑将其与此进行聚类。听起来不错?
由于我几乎总是按RootId
和User
进行过滤,因此我想将它们包含在我的索引中。将其他列包含在聚簇索引中是一个好主意吗?或者他们应该在一个单独的覆盖索引?
每个索引都需要唯一标识行,因此即使我没有指定主链,我的聚簇索引也会包含主键。所以使用Guid
作为PK似乎是存储的一个坏主意,特别是有1亿行。所以我使用的是bigint
。
由于我的PK不是聚集的(因此没有以该顺序物理存储),SQL Server如何计算下一个身份?我怀疑它是否对PK进行排序以找到最大值。在非聚集列上使用标识是个坏主意吗?
另外,我想我可以使用datetime2
精度为3(存储7个字节)而不是datetime
(8个字节)来保持相同的精度,但节省了一点空间(甚至精度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会很高兴不等待查询返回的年龄)
一旦插入,AuditLog行永远不会更新或删除。
典型的过滤器和订单:
PS:我清楚过程和时间,创建临时新表,以块的形式复制数据,创建索引等......
答案 0 :(得分:1)
由于我的大多数用法包括按日期排序的日期和顺序,我正在考虑使用它进行聚类。听起来不错?
没有这样做并且评估结果就没有办法知道。
在聚集索引中包含其他列是否是个好主意?
您不能在聚集索引中包含列,因为它没有多大意义。聚簇索引最终表。您在NC索引中包含列以避免进行其他查找以访问行的其他列。
SQL Server如何计算下一个身份?
坦率地说,不要担心。引擎管理表级别的标识 - 它不需要引用任何特定行来确定下一个值。
另外,我想我可以使用datetime2和精度3(存储7字节)而不是datetime(8字节)来保持相同的精度但节省一点空间(甚至精度4以提高相同存储的精度)反正)?
请勿仅限每行保存一个字节。根据您的要求选择正确的数据类型。存储很便宜。缺乏精确性是永远的。
此外,您的脚注不清楚。您指的是添加/更新/删除用户实体字段(对于那些不熟悉您的模式的人来说这是一个毫无意义的术语),也指“从不更新或删除”。这似乎是一个矛盾,可能相关也可能不相关。
最后一条评论。变革涉及风险。如果您当前的架构已足够,那么最安全方法是简单地使用您的ID列作为标识重新创建您的表(并且其他所有内容保持不变)。