我有以下查询从十万行项目中选择项目及其中一项功能。
但我担心子查询的性能。它会在where子句之后还是之前执行?
假设我从10000个项目中选择了25个项目,这个子查询将仅针对25个项目或10000个项目执行?
declare @BlockStart int = 1
, @BlockSize int = 25
;
select *, (
select Value_Float
from Features B
where B.Feature_ModelID = Itm.ModelID
and B.Feature_PropertyID = 5
) as Price
from (
select *
, row_number() over (order by ModelID desc) as RowNumber
from Models
) Itm
where Itm.RowNumber >= @BlockStart
and Itm.RowNumber < @BlockStart + @BlockSize
order by ModelID desc
答案 0 :(得分:2)
FROM
子句中的子查询会生成一整套结果,但SELECT
子句中的子查询(一般!)只会针对最终结果集中包含的记录。
与所有SQL一样,涉及到一个查询优化器,它有时可能决定创建看似奇怪的执行计划。在这种情况下,我相信我们可以非常自信,但我需要提醒我们对SQL语言操作顺序进行彻底的概括。
继续,您是否看到了Sql Server 2012及更高版本中可用的OFFSET/FECTH
语法?这似乎是处理@BlockStart
和@BlockSize
值的更好方法,尤其是it looks like you're paging on the clustered key.(如果您最终在备用列上进行分页,则链接显示多强>快的方法)。
此外,如果您知道每Features
ModelID
只有一个Feature_PropertyID = 5
记录存在风险,如果您再次进行概括,则将倾向于使用JOIN获得更好的性能:
SELECT m.*, f.Value_Float As Price
FROM Models m
LEFT JOIN Features f ON f.Feature_ModelID = m.ModelID AND f.Feature_PropertyID = 5
ORDER BY m.ModelID DESC
OFFSET @BlockStart ROWS FETCH NEXT @BlockSize ROWS ONLY
如果您无法保证,那么可以通过APPLY操作获得更好的效果:
SELECT m.*, f.Value_Float As Price
FROM Models m
OUTER APPLY (
SELECT TOP 1 Value_Float
FROM Features f
WHERE f.Feature_ModelID = m.ModelID AND f.Feature_PropertyID = 5
) f
ORDER BY m.ModelID DESC
OFFSET @BlockStart ROWS FETCH NEXT @BlockSize ROWS ONLY
最后,这有点像实体 - 属性 - 价值模式的另一种变体......虽然它有它的位置,但通常应该是最后的模式。