索引优化器提示建议准吗?备份前别盲目听它的

上周帮朋友恢复一个误删的数据库,他信誓旦旦说:“我按SQL Server Management Studio弹出的‘建议创建索引提示操作了,性能应该没问题。”结果一跑全量备份脚本,磁盘IO直接飙到98%,备份卡在37%不动——那条被推荐的非聚集索引,恰恰把WHERE条件里用的字段建成了INCLUDE列,反而让备份时的扫描路径变笨重。

器不是预言家,是“按当前快照算账”的会计

索引优化器(比如SQL Server的Database Engine Tuning Advisor、MySQL的EXPLAIN ANALYZE建议、PostgreSQL的pg_stat_statements触发的hint)本质上不看未来,只看它手头那几秒的查询执行计划和统计信息快照。你刚清空过表、刚插入10万测试数据、刚更新过统计信息——它看到的“成本模型”就完全不同。备份场景更特殊:备份过程本身会触发大量顺序读、页级锁、日志刷盘,而优化器建议压根不模拟这些后台行为。

备份时最怕的“伪优化”索引

常见翻车点有这几个:

  • 为备份常扫的系统视图(如sys.backupset、msdb.dbo.backupmediafamily)建索引——但这些表本身极小,加索引反而拖慢备份元数据写入;
  • 听建议给备份目标路径字段(比如physical_device_name)建索引——可这字段全是长字符串,B树索引碎片高,备份时INSERT新记录反而更慢;
  • 在备份前临时建个“加速SELECT COUNT(*)”的索引,结果备份进程被阻塞在等待该索引的共享锁上。

某次处理客户现场,他们按Azure SQL自动建议,在backupset表的backup_start_date上加了降序索引。结果每周日全备时,备份作业总在凌晨2:15卡住4分钟——查出来是那个索引导致backupset表的INSERT并发锁升级,而备份服务端恰好在那一刻批量写入上百条记录。

比听建议更靠谱的三件事

第一,备份前先看统计信息是否陈旧:

DBCC SHOW_STATISTICS ('msdb.dbo.backupset', 'backup_start_date')
如果last_updated是三个月前,别急着建索引,先UPDATE STATISTICS msdb.dbo.backupset;

第二,用真实备份负载测:在测试库跑一遍完整备份+校验,用SQL Server Profiler抓“Backup:Database”事件耗时,再对比加索引前后差异,差1秒以上才值得动;

第三,盯紧tempdb——很多优化器建议的“覆盖索引”会把大量字段INCLUDE进去,备份过程中排序、哈希操作全挤在tempdb,反而引发I/O争抢。这时候删掉花哨索引,留个精简的主键+时间字段组合索引,往往更稳。

说白了,优化器提示像天气预报——告诉你此刻云层厚度,但刮不刮风、下不下冰雹,得看备份时服务器的实际负载、磁盘队列深度、甚至机房空调是不是刚跳闸。信它一半,另一半得自己拿备份日志和perfmon数据对证。