比较 T-SQL Between 和 '<' '>' 运算符的性能差异?

Posted

技术标签:

【中文标题】比较 T-SQL Between 和 \'<\' \'>\' 运算符的性能差异?【英文标题】:Compare performance difference of T-SQL Between and '<' '>' operator?比较 T-SQL Between 和 '<' '>' 运算符的性能差异? 【发布时间】:2009-05-28 14:56:38 【问题描述】:

我尝试通过搜索引擎、MSDN 等进行搜索。但什么也做不了。抱歉,如果之前有人问过这个问题。使用 T-SQL 的“Between”关键字和使用比较运算符之间有性能差异吗?

【问题讨论】:

【参考方案1】:

您可以通过在这两种情况下检查查询计划来轻松地检查这一点。我知道这没有区别。 BETWEEN 和“”之间存在逻辑差异...... BETWEEN 是包容性的。它相当于“”。

【讨论】:

【参考方案2】:

查询引擎在&gt;=&lt;= 之间进行转换(查看查询计划),因此在实践中它们是相同的,理论上&gt;= &lt;= 更快,因为引擎不必翻译。祝你好运,但注意到不同之处。

反正我用的是 between,我觉得它读起来更容易

具有大量比较的非常复杂的查询/嵌套视图可能会从更改为 &gt;= &lt;= 中受益,因为这可能会通过减少重构查询所花费的时间来防止优化超时(只是一个理论,未经我测试,我从来没有注意到了)

【讨论】:

【参考方案3】:

喜欢人们提供代码来进行自己的测试,但您需要进行更大的子集/重复测试以说明加载到内存中的索引等......不过,在得出结论之前。这是具有更大表和 10 次迭代的相同代码

DECLARE
    @Startdatetime datetime ,
    @Diff int = 0 ,
    @Addrowcount int = 1000 ,
    @ptr int = 1;


SET NOCOUNT ON;

--Create a tempory table to perform our tests on
DROP TABLE dbo.perftest

CREATE TABLE dbo.perftest( id int NOT NULL
                                       IDENTITY(1 , 1)
                                       PRIMARY KEY ,
                           mytext nvarchar( 50 )NOT NULL );

--Now add some sample rows

SET @Addrowcount = 20000;

WHILE(@Addrowcount > 0)

    BEGIN

        INSERT INTO dbo.perftest( mytext )
        VALUES( 'thetext' );

        SET @Addrowcount = @Addrowcount - 1;

    END;

WHILE @ptr < 10 -- do this a few times to account for indexes being loaded into memory

BEGIN

    SELECT @Startdatetime = GETDATE();

    -- do method 1 here

    SELECT mytext
      FROM dbo.perftest
      WHERE(id >= (100 + (@ptr * 1000)))
       AND (id <= (500 + (@ptr * 1000)));

    --end method1

    SELECT @Diff = DATEDIFF( millisecond , @Startdatetime , GETDATE());

    PRINT ':Method 1: ' + CAST(@Diff AS nvarchar( 20 )) + ' ms';

    --reset start time

    SELECT @Startdatetime = GETDATE();

    --do method2 here

    SELECT mytext
      FROM dbo.perftest
      WHERE id BETWEEN (300 + (@ptr * 1000))
        AND (800 + (@ptr * 1000));

    --end method2

    SELECT @Diff = DATEDIFF( millisecond , @Startdatetime , GETDATE());

    PRINT ':Method 2: ' + CAST(@Diff AS nvarchar( 20 )) + ' ms';

    SET @ptr = @ptr + 1

END

给你一组非常不同的结果:

--Method 1    -- 10 ms
--Method 2    -- 33 ms
--Method 1    -- 40 ms
--Method 2    -- 26 ms
--Method 1    -- 23 ms
--Method 2    -- 23 ms
--Method 1    -- 13 ms
--Method 2    -- 16 ms
--Method 1    -- 13 ms
--Method 2    -- 20 ms
--Method 1    -- 6 ms
--Method 2    -- 16 ms
--Method 1    -- 26 ms
--Method 2    -- 16 ms
--Method 1    -- 13 ms
--Method 2    -- 13 ms
--Method 1    -- 16 ms
--Method 2    -- 13 ms

我会说从这个(仍然很不科学的)测试来看,两种方式都没有太大区别。

【讨论】:

【参考方案4】:

我还对使用 (>= 和 = 样式运算符)。 这是我使用的脚本:

DECLARE
    @Startdatetime datetime ,
    @Diff int = 0 ,
    @Addrowcount int = 1000;

SET NOCOUNT ON;

--Create a tempory table to perform our tests on

CREATE TABLE dbo.perftest( id smallint NOT NULL
                                       IDENTITY(1 , 1)
                                       PRIMARY KEY ,
                           mytext nvarchar( 50 )NOT NULL );

--Now add some sample rows

SET @Addrowcount = 1000;

WHILE(@Addrowcount > 0)

    BEGIN

        INSERT INTO dbo.perftest( mytext )
        VALUES( 'thetext' );

        SET @Addrowcount = @Addrowcount - 1;

    END;

SELECT @Startdatetime = GETDATE();

-- do method 1 here

SELECT mytext
  FROM dbo.perftest
  WHERE(id >= 100)
   AND (id <= 900);

--end method1

SELECT @Diff = DATEDIFF( millisecond , @Startdatetime , GETDATE());

PRINT ':Method 1: ' + CAST(@Diff AS nvarchar( 20 )) + ' ms';

--reset start time

SELECT @Startdatetime = GETDATE();

--do method2 here

SELECT mytext
  FROM dbo.perftest
  WHERE id BETWEEN 100
    AND 900;

--end method2

SELECT @Diff = DATEDIFF( millisecond , @Startdatetime , GETDATE());

PRINT ':Method 2: ' + CAST(@Diff AS nvarchar( 20 )) + ' ms';

结果是:

方法 1:140 毫秒

方法 2:70 毫秒

所以看来使用 between 可以提高性能。

【讨论】:

不确定这样的测试有多有效...我想和任何简单的配置文件测试一样有效,但这并不能说明什么。基于缓存(您刚刚添加记录)以及当时没有其他事情发生(与现实世界的服务器不同)以及同时添加所有记录,而不是在多个页面/时间上被碎片化,可能会有很大不同. 运行相同的测试几百次并提供每种方法的平均时间会很有用。【参考方案5】:

这里要相互比较的两个运算符根本不同,因此生成的执行计划也可能不同(尽管不能保证)。

决定因素是应用比较运算符的列的数据分布(选择性)。这与统计信息一起将决定是否使用索引等。

希望这是有道理的。

【讨论】:

不知道为什么这被否决了。约翰有没有说错话?有人感觉不是很好吗?有人有什么想法吗? 我从未更改过原始问题。我也没有投反对票。 vs = 并不是根本的区别,但这可能就是它被否决的原因。应该考虑一个小的逻辑差异,并且性能差异绝对为零。【参考方案6】:

事实上。我只是尝试使用我的一些数据进行验证。 BETWEEN 等价于 ">=" 和 "

【讨论】:

不,这是不正确的。你确定你有精确到毫秒的5/30/2010 00:00:00.000 数据吗? 这与文档相矛盾,这意味着如果这是真的,那就是一个错误。我倾向于同意史密斯先生的观点,即数据可能有误。【参考方案7】:

在更复杂的查询中,您无法事先知道要与之比较的最小值或最大值,那么使用 BETWEEN 几乎等同于使用 >= 和

但是,当您事先确切知道最小值和最大值是什么时,不使用 BETWEEN 运算符而是将所需结果与最小值以下 1 个数字和最大值以上 1 个数字进行比较会更便宜。

SELECT n.Number FROM dbo.Numbers AS n
WHERE n.Number BETWEEN 1 AND 100

几乎等同于:

SELECT n.Number FROM dbo.Numbers AS n
WHERE n.Number >= 1 AND n.Number <= 100

每行分别针对 >、

宁可这样做:

SELECT n.Number FROM dbo.Numbers AS n
WHERE n.Number > 0 AND n.Number < 101

每行仅针对 > 和 <.> 进行比较

【讨论】:

以上是关于比较 T-SQL Between 和 '<' '>' 运算符的性能差异?的主要内容,如果未能解决你的问题,请参考以下文章

日期比较 BETWEEN vs < >

T-SQL:比较 2 个 XML 并返回具有不同值的节点

HQL 中的 between 是不是严格比较?

CONCAT 或 APPEND T-SQL 中的两个别名列

BETWEEN 子句与 <= AND >=

BETWEEN 子句与 <= AND >=