我当时使用CROSS APPLY来连接Users和GeoPhone表,并且一切工作都很快,但是现在我在Phone列中有具有NULL值的Users。交叉应用会在最终输出中跳过这些行。所以我切换到OUTER APPLY。但是它的工作速度非常慢(当输出的总行数仅增加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 <= dbo.GeoPhone.[End] OR dbo.Users.Phone IS NULL,结果相同,但速度慢得多。
WHERE dbo.Users.Phone <= dbo.GeoPhone.[End] OR dbo.Users.Phone IS NULL
请随时对此发表评论。
CROSS APPLY是特定于MSSQL的… APPLY上的Microsoft
APPLY导致右侧查询对左侧查询中的每个结果执行一次。CROSS仅考虑匹配行,例如INNER JOIN。使用OUTER会考虑左侧查询中的所有行。多余的行会伤人。
我建议您重新构造右侧查询以显式接受NULL,而不要使用OUTER APPLY。