【问题标题】:CROSS APPLY vs OUTER APPLY speed differenceCROSS APPLY 与 OUTER APPLY 速度差异
【发布时间】:2011-10-07 06:55:57
【问题描述】:

我使用 CROSS APPLY 来加入用户和 GeoPhone 表,一切都运行得很快,但现在我的用户在电话列中有 NULL 值。交叉应用会在最终输出中跳过这些行。所以我切换到外部应用。但它的运行速度要慢得多(当输出中的总行数仅增加 1000 行时,速度会慢 15 倍以上)。

SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country
FROM  dbo.Users CROSS APPLY
                 (SELECT TOP 1 Country
                 FROM    dbo.GeoPhone
                 WHERE dbo.Users.Phone <= dbo.GeoPhone.[End]) GeoPhone

对比:

SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country
FROM  dbo.Users OUTER APPLY
                 (SELECT TOP 1 Country
                 FROM    dbo.GeoPhone
                 WHERE dbo.Users.Phone <= dbo.GeoPhone.[End]) GeoPhone

我试图理解为什么。正如我所见,执行计划不同。但理论上我看不到任何可能导致这种减速的计算。

有什么想法吗?

我的最终解决方案:

SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country
FROM  dbo.Users CROSS APPLY
                 (SELECT TOP 1 Country
                 FROM    dbo.GeoPhone
                 WHERE ISNULL(dbo.Users.Phone, 0) <= dbo.GeoPhone.[End]) GeoPhone

这为非空电话分配实际国家,为空电话分配第一个范围的国家(对于我的案例来说,这已经是“未知”)。出于某种原因,WHERE dbo.Users.Phone &lt;= dbo.GeoPhone.[End] OR dbo.Users.Phone IS NULL 的结果相同,但速度要慢得多。

请随时发表评论。

【问题讨论】:

    标签: sql sql-server performance tsql


    【解决方案1】:

    你可以试试这个:

    SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country
    FROM  dbo.Users CROSS APPLY
                     (SELECT TOP 1 Country
                     FROM    dbo.GeoPhone
                     WHERE dbo.Users.Phone <= dbo.GeoPhone.[End]) GeoPhone
    UNION ALL
    SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, NULL AS Country
    FROM  dbo.Users
    WHERE dbo.Users.Phone IS NULL
    

    确保您在 dbo.Users.Phone 上有一个索引

    【讨论】:

    • 这工作很快!!但我找到了稍微快一点的解决方案。我将其添加到我的问题中。
    【解决方案2】:

    CROSS APPLY 是特定于 MSSQL 的...Microsoft on APPLY

    APPLY 使右侧查询在左侧查询中的每个结果执行一次。 CROSS 只考虑匹配行,如 INNER JOIN。使用 OUTER 会考虑左侧查询中的所有行。多余的行很疼。

    我建议您重新编写右侧查询以明确接受 NULL 而不是使用 OUTER APPLY。

    【讨论】:

    • 谢谢Magicianeer,收到您的消息后,我尝试重新制定右侧查询并找到快速解决方案。我将它添加到第一条消息中。
    猜你喜欢
    • 2013-07-08
    • 2017-07-24
    • 2022-12-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多