假设我们有一个#RelevantOrders表和一个OrderRow表。
create table #RelevantOrders(Order_Id int primary key)
create talbe OrderRow (Order_Id int, OrderRow_Id, [lots of data columns], primary key (Order_Id, OrderRow_Id)现在,我本能地做了一个简单的连接
select OrderRow.* from #RelevantOrders as ro join OrderRow on OrderRow.Order_Id = ro.Order_Id现在,由于数据的原因,#RelevantOrders中的Order_Id是几个ie范围,即。1,2,3,4,5,100,101.120,240.250.希望我能说清楚。
那么,如果有1000个相关的订单,执行计划会在OrderRow表上查找1000个索引,每个Order_Id 1。这导致相当大的扫描计数和逻辑读取(~5000)。
所以它让我思考,我希望它不会做1000指数的搜索,它会做~80 (连续范围的数目)索引寻找。
所以我尝试了另一种选择:
create table #RelevantOrderRanges(f int, t int)
select OrderRow.* from #RelevantOrderRanges
join OrderRow on OrderRow.Order_Id between f and t好消息是索引查找的增加和逻辑读取下降到80索引查找(等于范围的数量)和609逻辑读取。好多了。我在这里遇到的唯一问题--这是因为我的经验导致占用内存--是估计的行数和估计的数据大小,在本例中,它的大小约为3.5GB,安装49 in。
现在我知道,如果范围数接近订单数量,任何收益都会丢失。
因此,这让我思考,我有两个问题:( 1)我是不是想得太多了?我知道还需要更多的测试,但我有点担心,由于内存占优势,估计结果会让我很难受。
( 2)有什么方法可以“更好地解释”SQL?指数,暗示,统计..。?
谢谢你的讨论
PERFORMANCE UPDATE:
TC 1:
Order_Id count: 9045
Range count: 5499
Total rows produced:
Range based approach:
~800ms CPU, ~800ms ellapsed time
Scan count: 5,500
Logical reads: 37,896
ID join approach:
~900ms CPU, ~900ms ellapsed time
Scan count: 9045
Logical reads: 56774
TC 2:
Order_Id count: 19684
Range count: 12849
Total rows produced: 124561
Range based approach:
~718ms CPU, ~770ms ellapsed time
Scan count: 12849
Logical reads: 74127
ID join approach:
~950ms CPU, ~950ms ellapsed time
Scan count: 19684
Logical reads: 110352发布于 2020-04-21 10:12:17
编辑。我误解了这个问题。我认为这是关于应用程序的设计,而不是查询性能。
对于应用程序:就个人而言,我将避免使用中间表。这只是额外的步骤和复杂。
#表对于查询是有意义的。
如果您有有用的索引,并且您的统计数据是最新的,您通常最好离开Server来决定最佳的执行计划。
根据数据的增长和分布,最佳执行计划可能会随着时间的推移而改变。所以我不愿意花费大量的时间和精力来压缩最后1%的额外性能。
https://dba.stackexchange.com/questions/265483
复制相似问题