Tri*_*nko 5 performance sql-server delete index-maintenance bulk-insert performance-tuning
存在一个“批量查询”表,它有两列(BatchID、RecordID),它们都是 TSQL 类型的“uniqueidentifier”。唯一的聚簇键在(BatchID,RecordID)上,并且没有二级索引。
我们使用 SqlBulkCopy 将数千或数百万个 id 快速插入到单个批处理 id 下的表中,以便各种查询可以加入它以使用与该批处理关联的记录 id 集执行过滤。这种方法比尝试多个查询快得多,所有查询都在查询字符串中发送 id 列表。查询完成后,该批记录 ID 将被删除。当没有查询运行时,该表平均为空,但可能有数百个活动批次,因为我们每秒处理数千个可能使用该表的 API 请求。
我的问题是,DBA 需要什么样的维护步骤(如果有)来维护这些表。例如,它是否会从定期索引重建中受益,或者 SQL Server 是否会自行处理已删除行的清理(释放页块等)。此外,表或聚集索引是否有任何特殊配置会有所帮助,特别是考虑到标识符是随机 Guids(唯一标识符)。
一般我们使用最新版本的SQL Server,企业版。有些服务器在 Azure 中,有些在 AWS 中。
我也有兴趣听取替代方案。例如,我认为这种方法最适合永久表,但我也可以创建一个会话本地临时表作为事务的一部分,该表在完成时被删除,而不是从永久表中插入和删除行。我只是不知道相比之下会如何表现。
小智 6
根据我在 SQL Server 2016 Enterprise Edition 中使用永久表作为消息队列的类似过程的经验 - 因此它具有非常高的插入和删除率 - 我们发现每 5 到 10 分钟重建索引有利于强制删除记录清理。这极大地提高了表的读取性能。
在我们的例子中,数据库隔离级别是读提交快照,出队/删除过程删除记录的速度比幽灵清理过程清除记录的速度快。对于高幻影记录计数,选择一条记录有时需要 1-3 秒而不是 5-10 毫秒,因为 SQL 必须读取所有幻影记录,这由高扫描计数(带有set statistics io on
)指示。
要检查幽灵记录的数量:
SELECT version_ghost_record_count, *
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('[transport].[BatchTable]'), NULL, NULL, 'SAMPLED')
Run Code Online (Sandbox Code Playgroud)
鬼清除过程会按一定时间间隔自动运行(SQL Server 2012+ 每 5 秒一次,SQL Server 2008/2008R2 每 10 秒一次)并检查是否有任何页面被标记为鬼记录。如果它找到任何,那么它会删除标记为删除或重影的记录,每次执行最多触及10 页。
在具有许多删除的高负载系统上,ghost 清理过程可能会导致性能问题,因为将页面保留在缓冲池中并生成 IO
我认为“最多 10 页”部分是我们的限制因素,因为高删除率超过了每次运行清理过程可以触及的页面数量。