我有一个运行速度稍慢的查询。
SELECT b.BreakdownClassificationId,
k.IsinCode,
k.SedolCode,
ClassificationDate,
NAME,
InstrumentType,
GeographicalLocation,
CapSize,
Currency,
ExchangeName,
HoldingDomicile,
MaturityDate,
Sector,
MajorSector
FROM #BreakdownSet b
OUTER apply (SELECT TOP 1 IsinCode,
SedolCode,
ClassificationDate,
NAME,
InstrumentType,
GeographicalLocation,
CapSize CapSize,
Currency,
ExchangeName,
HoldingDomicile,
MaturityDate,
Sector,
MajorSector
FROM dbfinex.dbo.PfPortfolioHoldingClassificationFtid x WITH (nolock)
WHERE ( x.isincode > ''
AND x.isincode = b.breakdowncode )
OR ( x.sedolcode > ''
AND x.sedolcode = b.breakdowncode )
OR ( x.sedolcode > ''
AND x.sedolcode = b.sedolcode )
OR ( x.isincode > ''
AND x.isincode = b.isincode )
ORDER BY CASE
WHEN x.sedolcode = b.breakdowncode THEN 1
WHEN x.isincode = b.breakdowncode THEN 2
WHEN x.sedolcode = b.sedolcode THEN 3
WHEN x.isincode = b.isincode THEN 4
ELSE 5
END,
classificationdate DESC) k
执行计划
Order By
里面Cross Apply
是非常昂贵的,有没有更好的方法来编写这个查询?
如果您愿意,您可以取消排序,尽管很难说这是否有必要提高查询性能。关键是您如何构造
ORDER BY
子句以及搜索条件。如果有任何匹配的行,x.sedolcode = b.breakdowncode
那么您想要获取该行,否则您转到下一个条件。使用正确的索引,我们可以通过拆分APPLY
. SQL Server 查询优化器实际上提供了一个很好的提示,因为它将您的OR
条件转换为UNION
s。我将创建一个有限的示例,以显示我所追求的一般查询计划形状。我还将假设该
PfPortfolioHoldingClassificationFtid
表在列上有一个主键和一个集群键PK
。这是我的测试数据:这是您对我的表定义的查询:
毫不奇怪,我得到了一个与你不同的计划,但这种类型的估计成本仍然很高。如果我们将其
APPLY
分成四个部分,并且每个部分APPLY
只返回表的主键呢?如果我们每个都有一个覆盖索引,APPLY
那么我们可以通过最多四个索引查找找到匹配行的主键。不需要排序。我们也可以通过在 s 中添加过滤器来跳过不需要的搜索,APPLY
但这并不能保证行为。这是编写它的一种方法:临时表中有 150 万行,最坏的情况应该是 600 万次非聚集索引查找和 150 万次聚集索引查找。
查询在我的机器上运行两秒钟。运行时无关紧要,因为我有无意义的数据。但是,计划中没有排序。我将查询计划上传到Paste The Plan。您应该考虑为将来的问题也这样做。这也是实际计划的屏幕截图:
您拥有的查询执行嵌套循环连接并且不会并行。使用
LOOP JOIN
并MAXDOP 1
提示查询在我的机器上七秒内完成。这是计划,这是屏幕截图: