查询:
SELECT Object1.Column1, Object2.Column2 AS Column3, Object2.Column4 AS Column5,
Object3.Column6, Object3.Column7,Object1.Column8, Object1.Column9,
Object1.Column10, Object1.Column11, Object1.Column12, Object1.Column13,
Object1.Column14, Object1.Column15 as Column15, Object1.Column16,
Object4.Column4 AS Column17, Object4.Column2 AS Column18, Object1.Column19,
Object1.Column20, Object1.Column21, Object1.Column22, Object1.Column23,
Object1.Column24, Object1.Column25, Object1.Column26, Object5.Column4,
Object1.Column27, Object1.Column28, Object1.Column29, Object3.Column30,
Object3.Column1 as Column31, Object3.Column32 as Column33, Object1.Column34
as Column34, ? AS Column35 , Object3.Column36 as Column37
FROM Object6 AS Object1
INNER JOIN Object7 AS Object3 ON Object1.Column38 = Object3.Column1
INNER JOIN Object8 AS Object2 ON Object3.Column30 = Object2.Column1
LEFT JOIN Object9 AS Object4 ON Object1.Column16 = Object4.Column2
LEFT JOIN Object10 AS Object5 ON Object1.Column9 = Object5.Column2
WHERE Object2.Column1 <> ? AND Object1.Column8 = ?
AND ( coalesce(Column16,?)= ? )
AND EXISTS (
SELECT ?
FROM Object11
WHERE Column39 = ?
AND Column30 = Object3.Column30)
ORDER BY Column7 desc
OFFSET ? ROWS FETCH FIRST ? ROWS ONLY
我知道我应该为此添加一个索引:
Database1.Schema1.Object7.Column30, Database1.Schema1.Object7.Column36, Database1.Schema1.Object7.Column6, Database1.Schema1.Object7.Column32
但是其中一列是 varchar 4000,由于该字段的尺寸很大,因此无法创建它。
我注意到仅当返回的行少于获取的第一个数字时才需要 25 秒
执行计划
Object7
首先使用非覆盖索引按Column7
顺序访问。然后它对该表进行一些键查找,并针对其他表进行嵌套循环连接,最终连接结果到达TOP
运算符时仍然按Column7
.一旦它收到足够的行来满足它,
OFFSET ... FETCH
它就可以停止从下游操作员那里请求更多的行。Object7.Column7
SQL Server 估计在到达该点之前它只需要从初始索引读取 2419 行。这个估计根本不正确。事实上,在满足
Object7
之前,它最终会读取全部行并且可能会用完所有行OFFSET ... FETCH
。半连接
Object11
将行数减少了将近一半,但杀手是Object6
同一张表上的连接和谓词。这些一起减少了9,753,116
来自半连接的行2
。您可以尝试花一些时间查看所涉及表的统计数据,以尝试从这些连接中获得基数估计更准确,或者您可以添加
OPTION (USE HINT ('DISABLE_OPTIMIZER_ROWGOAL') )
,以便计划在不假设它可以提前停止的情况下计算成本OFFSET ... FETCH
- 这个肯定会给你一个不同的计划。如果您可以在 Object11 上添加一个索引,Column39 + Column30,并在 Object7 上添加一个索引,Column30,以及在对象 7
INCLUDE
的语句部分中来自 Object7 的其他字段CREATE INDEX
,您应该会有很大的性能提升。这是此查询中涉及的绝大部分资源支出。根据计划的 XML,这些似乎接近于此查询的最佳索引: