一、创建合适的索引类型
ORDER BY、BETWEEN)的列(如OrderDate),每个表只能有一个聚集索引。其物理存储顺序与索引逻辑顺序一致,能大幅提升顺序访问性能。CustomerID),逻辑顺序与物理存储无关。每个表可有多个非聚集索引,能有效加速点查询(如WHERE CustomerID = 100)。CREATE NONCLUSTERED INDEX idx_Orders_Covering ON Orders (CustomerID) INCLUDE (OrderDate, TotalAmount)),查询可直接从索引中获取数据,避免回表操作,显著减少I/O开销。CREATE NONCLUSTERED INDEX idx_ActiveProducts ON Products (ProductID) WHERE IsActive = 1),适用于频繁过滤的列,能减少索引大小并提高查询效率。二、优化索引列选择
CustomerID,假设唯一值占比高),避免选择低选择性列(如Gender,男女比例接近)。高选择性列能更有效地缩小查询范围,提升索引效率。CREATE NONCLUSTERED INDEX idx_OrderQuery ON Orders (CustomerID, OrderDate))。复合索引遵循“最左前缀”原则,前面的列能过滤更多数据,后面的列辅助细化查询。UPDATE语句需维护所有相关索引)。定期审查索引,删除未使用或冗余的索引(如通过sys.dm_db_index_usage_stats查看索引使用情况)。三、定期维护索引
ALTER INDEX REORGANIZE重组索引,减少碎片但不收缩文件;ALTER INDEX REBUILD重建索引,彻底整理碎片并收缩文件(重建时需考虑锁表影响,可在低峰期执行)。UPDATE STATISTICS TableName),确保优化器选择最优执行计划。四、避免索引失效场景
SELECT * FROM Orders WHERE YEAR(OrderDate) = 2025,会导致索引失效。应改为SELECT * FROM Orders WHERE OrderDate >= '2025-01-01' AND OrderDate < '2026-01-01'。LIKE '%value%'会导致索引失效,应使用LIKE 'value%'(前导字符固定)或全文索引替代。SELECT * FROM Orders WHERE CustomerID = 100 OR ProductID = 200,若ProductID无索引,会导致全表扫描。可将OR改为UNION ALL(如SELECT * FROM Orders WHERE CustomerID = 100 UNION ALL SELECT * FROM Orders WHERE ProductID = 200)。NOT EXISTS或范围查询替代(如SELECT * FROM Orders WHERE CustomerID NOT IN (1,2)改为SELECT * FROM Orders WHERE NOT EXISTS (SELECT 1 FROM Customers WHERE Customers.CustomerID = Orders.CustomerID AND Customers.CustomerID IN (1,2)))。五、利用SQL Server特性优化
CREATE NONCLUSTERED COLUMNSTORE INDEX IX_SalesOrderDetail_ColumnStore ON Sales.SalesOrderDetail (UnitPrice, OrderQty, ProductID)。MEMORY_OPTIMIZED = ON)和本机编译存储过程(WITH NATIVE_COMPILATION),提升高频事务处理性能(如订单处理)。需将数据库兼容级别设置为130及以上(ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL = 130)。sys.dm_db_index_usage_stats查看索引的扫描、查找、更新次数,识别未使用或低效索引(如SELECT * FROM sys.dm_db_index_usage_stats WHERE database_id = DB_ID('YourDB'))。