我有一个SQL Server数据库,想要优化我最常执行的查询。
数据库很简单,它跟踪离开我工厂的交货单的状态。出于这个问题的目的,让我们假设我的数据库只包含4个表,第一个是Delivery Master表,包含传递ID(int),类型(tinyint),位置(tinyint)和状态(tinyint),另一个三个表是查找表,用于将用于类型,位置和状态的数字与文本字符串相关联(例如Status:1 ='Open',2 ='Picking',3 ='On-Dock'...)
最常执行的查询是交付摘要(位于Web应用程序的主页面上)它是所有交付的枢轴,其中行字段是类型和位置,列标题是状态:
[Location] | [Type] | [1(Open)] | [2] | [3] | [4] | ...
----------------------------------------------------------
'LocationA' | 'TypeA' | 1 | 2 | 3 | 4 | ...
'LocationA' | 'TypeB' | 5 | 6 | 7 | 8 | ...
'LocationB' | 'TypeA' | 9 | 10 | 11 | 12 | ...
...
平均而言,此查询需要100毫秒才能运行(这对于在主表中的每一行上执行日期计算并且在更多字段上使用加权平均值进行聚合的更复杂的查询比这个仅计算行数的查询花费的时间更少)
当我查看执行计划时,我发现超过一半的执行时间花费在具有 6条记录(类型)的表上执行聚簇索引扫描。
仓库(位置)表使用非聚集索引进行扫描,只占执行时间的3%(但该表只有5条记录,我确定会产生巨大差异)
我在类型表上创建了一个非聚集索引,但即使我删除旧的执行计划并强制它创建一个新的执行计划,查询优化器也不会使用它。
这是正在执行的SQL
SELECT TOP (500)
Warehouse, WarehouseDescrip, Type, TypeDescrip,
[1] AS Open_DO, [2] AS In_Process, [3] AS On_Dock, [4] AS Revision, [5] AS Complete
FROM
(SELECT
Static.Warehouse.Description AS WarehouseDescrip,
Static.DOType.Description AS TypeDescrip,
DOInfo.DOMaster.Status, DOInfo.DOMaster.DONum,
DOInfo.DOMaster.Type, DOInfo.DOMaster.Warehouse
FROM
DOInfo.DOMaster
INNER JOIN
Static.DOType ON DOInfo.DOMaster.Type = Static.DOType.ID
INNER JOIN
Static.Warehouse ON DOInfo.DOMaster.Warehouse = Static.Warehouse.ID
WHERE
(DOInfo.DOMaster.Status <> 6)) ps
PIVOT
(COUNT(DONum) FOR Status IN ([1], [2], [3], [4], [5])) AS pvt
ORDER BY
Warehouse ASC, Type ASC
执行计划的屏幕截图: