【发布时间】:2018-08-04 08:51:59
【问题描述】:
使用 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# 仍然)生成的主键。我认为我的选择是int identity 和guid(默认为NEWSEQUENTIALID)。
由于我的大部分用法包括日期和按日期排序,我正在考虑使用它进行聚类。听起来对吗?
由于我几乎总是按RootId 和User 进行过滤,因此我正在考虑将它们包含在我的索引中。将其他列包含在聚集索引中是个好主意吗?还是应该在单独的覆盖索引中?
每个索引都需要唯一标识行,因此即使我没有指定主键,我的聚集索引也会包含主键。因此,使用Guid 作为 PK 对于存储来说似乎是个坏主意,尤其是在有 1 亿行的情况下。所以我使用的是bigint。
由于我的 PK 不是集群的(因此没有按该顺序物理存储),SQL Server 如何计算出下一个标识?我怀疑它对 PK 进行排序以找到最大值。在非聚集列上使用标识是个坏主意吗?
另外,我想我可以使用精度为 3(存储 7 个字节)的 datetime2 而不是 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 行一旦插入就永远不会更新或删除。
典型的过滤器和顺序:
- 仅按日期过滤
- 按日期和用户过滤
- 按日期和 objectId 过滤
- 按日期、用户和对象 ID 过滤
- 仅按 objectId 过滤
- 几乎总是按反向日期排序,以首先显示最近的更改。
- 通常与分页一起使用,使用“偏移 x 行”和“仅获取下 x 行”
- 和一个特定用例,相当于使用 where 子句选择 PK 的子集,然后使用 PK 在主表上自联接以检索列值
PS:我很清楚这个过程和需要的时间,创建临时新表,分块复制数据,创建索引等等......
【问题讨论】:
-
您是否考虑过为该表使用聚集列存储? docs.microsoft.com/en-us/sql/relational-databases/indexes/…
标签: sql-server database indexing