SQL Server查询中的操作顺序

时间:2018-02-12 19:57:48

标签: sql sql-server subquery

我有以下查询从十万行项目中选择项目及其中一项功能。

但我担心子查询的性能。它会在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

1 个答案:

答案 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

最后,这有点像实体 - 属性 - 价值模式的另一种变体......虽然它有它的位置,但通常应该是最后的模式。