zoukankan      html  css  js  c++  java
  • WHERE条件中or与union引起的全表扫描的问题

     说起数据库的SQL语句执行效率的问题,就不得不提where条件语句中的or(逻辑或)引起的全表扫描问题,从而导致效率下降。

        在以往绝大多数的资料中,大多数人的建议是使用 union 代替 or ,以解决由于使用了 OR 导致的全表扫描。然而,实际是不是如此呢?flymorn就拿5万多条数据的MSSQL数据库来测试。

        在SQL Server查询分析器中键入如下代码:

    SET STATISTICS profile ON
    SET STATISTICS io ON
    SET STATISTICS time ON 
    go
    select * from chuzu where c_id>1000 or c_qu='沙坪坝区' order by c_time desc select * from chuzu where c_id>1000 
    union
    select * from chuzu where c_qu='沙坪坝区' order by c_time desc
    go
    SET STATISTICS profile OFF
    SET STATISTICS io OFF
    SET STATISTICS time OFF

        数据库设计中,id为主键,同时也是聚集索引,qu是普通字段列,两个条件中的字段是不一样的。

        执行计划如下:

    WHERE条件中or与union引起的全表扫描的问题

        从执行计划中可以看出,采用了 union 的SQL语句的查询成本为50.22%,比采用 or 的成本 49.78%稍多,当然这只是计划。我们再来看看执行效率:

    (所影响的行数为 52713 行)
    表 'chuzu'。扫描计数 1,逻辑读 2412 次,物理读 0 次,预读 0 次。
    SQL Server 执行时间: CPU 时间 = 938 毫秒,耗费时间 = 3222 毫秒。 (所影响的行数为 52713 行)
    表 'chuzu'。扫描计数 2,逻辑读 4774 次,物理读 0 次,预读 0 次。
    SQL Server 执行时间:  CPU 时间 = 1484 毫秒,耗费时间 = 4323 毫秒。

        从这样的数据可以看出,采用了 union 的SQL语句的效率(4323 毫秒)实际上并没有比采用 or (3222 毫秒) 的高,耗费的时间也要多,采用了 or 的效率反而高出了25%。

        如果where条件中的是同一个字段的话,执行效率也大体如上。

    SET STATISTICS profile ON
    SET STATISTICS io ON
    SET STATISTICS time ON 
    go
    select * from chuzu where c_qu='九龙坡区' or c_qu='沙坪坝区' order by c_time desc select * from chuzu where c_qu='九龙坡区'
    union
    select * from chuzu where c_qu='沙坪坝区' order by c_time desc
    go
    SET STATISTICS profile OFF
    SET STATISTICS io OFF
    SET STATISTICS time OFF

       在这样的执行计划中,union 成本为 60.75% ,采用 or 的成本为 39.25%。依然是or的效率高。

    WHERE条件中or与union引起的全表扫描的问题

       再来看执行结果:

    (所影响的行数为 6131 行)
    表 'chuzu'。扫描计数 1,逻辑读 2412 次,物理读 0 次,预读 0 次。
    SQL Server 执行时间:  CPU 时间 = 203 毫秒,耗费时间 = 635 毫秒。 (所影响的行数为 6131 行)
    表 'chuzu'。扫描计数 2,逻辑读 4824 次,物理读 0 次,预读 0 次。
    SQL Server 执行时间:  CPU 时间 = 360 毫秒,耗费时间 = 798 毫秒。

        采用union的执行时间 798 ms ,or的时间是 635ms,效率上来说,依然是 or 的效率高。

        总结:我的测试结果正和网上说的相反,也许是因为我的数据量还不够大,才5万多的数据;或许当数据量到了百万千万级的时候,union 的效率 就会比 or 的高了。

         所以,我的理解是在数据量还没有足够大,sql语句中还是尽量用 or 条件查询,因为数据量不大的情况下,即使全表扫描也要比逻辑读两次,扫描两次的时间要少,效率要高;当然,如果你的数据达到百万级别以上了,那就不要用 or 了,可以用 union 或 union all 代替 or ,以避免因为 or 引起的全表扫描。

  • 相关阅读:
    【Codechef】Chef and Bike(二维多项式插值)
    USACO 完结的一些感想
    USACO 6.5 Checker Challenge
    USACO 6.5 The Clocks
    USACO 6.5 Betsy's Tour (插头dp)
    USACO 6.5 Closed Fences
    USACO 6.4 Electric Fences
    USACO 6.5 All Latin Squares
    USACO 6.4 The Primes
    USACO 6.4 Wisconsin Squares
  • 原文地址:https://www.cnblogs.com/xxcn/p/3852215.html
Copyright © 2011-2022 走看看