【发布时间】:2021-09-13 09:39:32
【问题描述】:
我拥有的一个特定索引在一天内将其碎片增加到 50%。 该表保存 SMS 消息请求的日志。 架构 -
RequestId(int), primary key, auto increment
ProviderRequestId(nvarchar(350)), nullable
RelationField1 (int)
RelationField2 (int)
RelationField3 (int)
RelationField4 (int)
....
索引 - ProviderRequestId 上的非聚集索引。 (不包含列)
导致碎片增长的过程-
为了发出请求,我必须将生成的RequestId 发送给提供者。
之后,他回复了ProviderRequestId。
所以我首先在ProviderRequestId 中插入一个带有NULL 值的请求。
当提供者响应时,我通过RequestId 用收到的ProviderRequestId 更新插入的行。
上述过程有时会在一天内并行发生一百万次,因此基本上,数百万行以 NULL 值插入到表中,然后进行更新。我猜这就是碎片化增长如此之快的原因。
之后,将在最初发送给提供者的RequestId 上进行多次快速所需的读取,这就是为什么我选择使用聚集索引,该索引要求我在收到来自提供者的响应之前插入行。
你会如何解决这个问题? 我应该每天只运行一次索引优化脚本吗? (https://ola.hallengren.com/sql-server-index-and-statistics-maintenance.html) 或者这是不好的做法,我应该只创建另一个整数列并在代码中管理它的值,以便我可以在插入行之前将请求发送给提供者?这将节省我上面提到的所有更新。 但需要一个额外的索引,并且可能不会像使用聚集索引进行读取那样高效。
很想听听你的想法,谢谢。
【问题讨论】:
-
我建议您在 dba.stackexchange.com 上提出这个问题。我对你的问题的想法:我想
ProviderRequestId是随机出现的,所以a)你是正确的,你需要定期对索引进行碎片整理,b)看看这个索引的 PAD_INDEX 和 FILLFACTOR。 -
如果您不需要索引中的非
NULLs,您可以使用过滤索引WHERE ProviderRequestId IS NULL删除它们。这可能会减少碎片的数量 -
@AlexYu 因为碎片化的快速增长定期意味着每天,这不是太多了吗?我会研究 PAD_INDEX 和 FILLFACTOR ty!
-
@Charlieface WUT,我只能索引非空行?!这听起来很完美!现在在谷歌上搜索,ty!
-
那将是相反的:
WHERE ProviderRequestId IS NOT NULL
标签: sql sql-server indexing