内连接vs where子句子查询sql server

时间:2015-01-30 10:23:27

标签: sql-server join where-clause sql-execution-plan logical-reads

我正在尝试加快我的存储过程,所以我使用下面的统计信息以两种格式测试我的存储过程

方法1:使用连接

set statistics io on 

select top 2000   
    p.Vehicleno, 
    dbo.GetVehicleStatusIcon1(p.Direction, StatusCode, 0) as 'Status',
    location,
    Convert(varchar(13), p.TrackTime, 102) + ' ' + Convert(varchar(13), p.TrackTime, 108) AS 'TrackTime',
    p.Speed, p.Ignition
from 
    pollingdata p 
inner join 
    assignvehicletouser asn on asn.vehicleno = p.vehicleno
where 
    asn.empid = 1

我将统计结果显示为

Table 'Worktable'. Scan count 943, logical reads 7671, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'AssignVehicleToUser'. Scan count 1, logical reads 41, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'PollingData'. Scan count 1, logical reads 50, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

方法2:使用where子句子查询

set statistics io on 

select top 2000 
    Vehicleno,
    dbo.GetVehicleStatusIcon1(Direction,StatusCode, 0) as 'Status',
    location,
    Convert(varchar(13), TrackTime, 102) + ' ' + Convert(varchar(13), TrackTime, 108) AS 'TrackTime',
    Speed, Ignition
from 
    pollingdata 
where 
    vehicleno in (select vehicleno 
                  from assignvehicletouser 
                  where empid = 1)

我将统计结果显示为

Table 'PollingData'. Scan count 1, logical reads 50, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'AssignVehicleToUser'. Scan count 1, logical reads 41, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

需要知道哪一个最好用?

需要解释逻辑读取的工作原理吗?

3 个答案:

答案 0 :(得分:7)

如果您不需要assignvehicletouser表中的任何内容,我更喜欢EXISTS(它可能与IN的工作方式相同)

SELECT TOP (2000) p.Vehicleno
    , dbo.GetVehicleStatusIcon1(p.Direction, StatusCode, 0) AS 'Status'
    , location
    , CONVERT(VARCHAR(13), p.TrackTime, 102) + ' ' + CONVERT(VARCHAR(13), p.TrackTime, 108) AS 'TrackTime'
    , p.Speed
    , p.Ignition
FROM pollingdata p
WHERE EXISTS (
        SELECT 1
        FROM assignvehicletouser asn
        WHERE asn.vehicleno = p.vehicleno
            AND asn.empid = 1
        );

答案 1 :(得分:1)

基于统计结果提供的第二个似乎更好,因为第一个有额外的tempdb“worktable”操作,用于保存临时/中间操作/结果,如SORTING操作

Logical Read每次从SQL Server缓冲区缓存中读取页面时都会发生逻辑读取,这很好。

物理读取:当缓冲区缓存中没有所需的数据页,系统从磁盘(物理IO)读取并复制到缓冲区缓存时,会发生这种情况。

您可以使用CROSS APPLY加入UDF而不是直接调用它,并且在第一个查询中WHERE条件(asn.emp = 1)可以在'ON'条件之后直接应用     asn.vehicleno = p.vehicleno AND asn.empid = 1

答案 2 :(得分:0)

通常joins will work faster than inner queries,但 reality it will depend on the execution plan generated by SQL Server

无论您如何编写查询,SQL Server都会始终根据执行计划对其进行转换。

如果“智能”足以从两个查询生成相同的计划,您将得到相同的结果。

您可以阅读Subquery or Joinhere