使用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 identity
和guid
(默认为NEWSEQUENTIALID
(。
由于我的大多数用法都包括日期和按日期订购,因此我正在考虑将其聚类。听起来对吗?
,由于我几乎总是按RootId
和User
过滤,因此我考虑将它们包括在我的索引中。在集群索引中包括其他列是一个好主意吗?还是应该在单独的覆盖索引中?
每个索引都需要唯一识别行,因此即使我不指定我的群集索引也将包含主键。因此,使用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列作为身份重新创建表(并且其他所有内容保持不变(。