SuperAPI AI 工具集

sqlserver-indexes

数据与分析

查看项目

更新于 10-16 06:06

技能介绍

用途

该技能用于 SQL Server 索引管理,目标是通过索引来改善查询性能。索引被描述为 SQL Server 查询性能最大的杠杆。该技能覆盖查找缺失索引、维护现有索引、消除未使用索引以及设计有效的覆盖索引。

主要能力

1. 缺失索引

SQL Server 会在执行查询时,通过 DMV 记录其识别到的索引机会。资料提醒这些并非完美建议,应将其视为线索。技能提供了脚本 ../scripts/missing-indexes.sql,其中包含一段 SQL,按影响分数排序返回前 20 条缺失索引。

影响分数的计算方式为 avg_user_impact * (user_seeks + user_scans),越高越重要。

对结果的解读:

  • equality_columns 成为前导键列。
  • inequality_columns 跟随等值列之后(范围谓词)。
  • included_columns 应通过 INCLUDE 覆盖 SELECT 列表,从而避免键查找。
  • 不要盲目创建每一条建议,应先合并相似的索引。
  • 列顺序规则:始终先放等值谓词,再放不等式谓词,然后是包含列。

2. 索引碎片

碎片会迫使 SQL Server 为读取相同数据读取更多页,从而降低性能。建议定期运行,多数工作负载为每月一次。技能提供脚本 ../scripts/index-fragmentation.sql,其中的查询会返回架构名、表名、索引名、类型、碎片百分比、页数、建议操作和维护语句。

决策指南:

  • 碎片小于 10%:跳过,不值得付出开销。
  • 碎片 10–30%:执行 REORGANIZE,在线、增量、开销低。
  • 碎片大于 30%:执行 REBUILD,更彻底;在 Enterprise Edition 上可使用 ONLINE = ON。

注意事项:

  • REBUILD 会自动更新统计信息;REORGANIZE 不会,需要单独运行 UPDATE STATISTICS。
  • ONLINE = ON 需要 Enterprise Edition,重建期间表保持可访问。
  • DMV 查询使用 SAMPLED 模式而非 DETAILED,在大型表上快得多。

3. 未使用索引

从未被读取但仍会在每次 INSERT/UPDATE/DELETE 时产生写入开销的索引属于纯浪费。技能提供脚本 ../scripts/unused-indexes.sql,查询会返回架构名、表名、索引名、类型以及各项用户操作统计,并生成被注释掉的 DROP 语句供审阅。查询条件包括用户查找、扫描、查找次数均为 0,用户更新次数大于 0,类型不为 CLUSTERED,且对象不是系统附带。

重要注意事项:

  • 使用统计会在 SQL Server 服务重启后重置,近期重启后不要使用该查询。
  • 索引可能被不频繁的批处理任务使用,删除前应核对其月度模式。
  • 某些索引用于强制约束(UNIQUE),应检查 i.is_unique_constraint。
  • 应先在开发或预发布环境测试删除。

4. 索引使用统计

技能提供一段查询,帮助理解索引实际如何被使用,返回架构名、表名、索引名、类型以及用户查找、扫描、查找次数、更新次数和最近一次查找、扫描时间等。

查找、扫描与查找的含义:

  • 查找(Seeks):最佳。SQL Server 通过 B 树键直接定位到特定行。
  • 扫描(Scans):SQL Server 读取整个索引或大范围。可能表示缺少谓词或索引不当。
  • 查找(Lookups):SQL Server 在非聚集索引中找到行,但必须回到聚集索引获取额外列。应通过覆盖索引修复。

5. 覆盖索引

覆盖索引让查询完全由索引满足,无需回表查找。

问题模式(键查找):资料以 Orders 表为例,包含 OrderID(主键)、CustomerID、OrderDate、Status、TotalAmount、Notes。查询选择 OrderDate、Status、TotalAmount 并按 CustomerID = 42 过滤。如果已有 CREATE INDEX IX_Orders_CustomerID ON Orders (CustomerID),SQL Server 会先查找 CustomerID = 42,然后为 OrderDate、Status、TotalAmount 做键查找。

修复方式是创建覆盖索引:

CREATE INDEX IX_Orders_CustomerID_Covering
ON Orders (CustomerID)
INCLUDE (OrderDate, Status, TotalAmount);

键列与 INCLUDE 列的区别:

  • 键列用于 WHERE、JOIN、ORDER BY,会被加入 B 树结构。
  • INCLUDE 列仅携带在叶级别,可为任意数据类型,不可搜索,用于满足 SELECT 列表。

使用方式

该技能以 SQL 脚本和查询形式提供,脚本路径包括 ../scripts/missing-indexes.sql、../scripts/index-fragmentation.sql、../scripts/unused-indexes.sql。用户可在 SQL Server 中运行这些查询以获取分析结果与维护语句。

适用场景与限制

适用场景为 SQL Server 索引的分析、维护与设计,包括排查缺失索引、处理碎片、清理未使用索引以及优化查询覆盖。限制包括:缺失索引建议并非完美,需要合并与人工判断;未使用索引的判断受统计重置影响,需考虑批处理模式和唯一约束;删除索引前应先在非生产环境测试。详细设计模式可参考 references/index-strategies.md,其中涉及复合键排序、筛选索引、列存储、维护计划等内容。