AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 167727
Accepted
user960567
user960567
Asked: 2017-03-22 04:17:01 +0800 CST2017-03-22 04:17:01 +0800 CST 2017-03-22 04:17:01 +0800 CST

有条件的 OR vs CASE vs IF

  • 772

可以说,我有一个问题,

SELECT * FROM MyTable WHERE MyParam = 0 OR MyColumn = MyParam

这里 MyParam 是参数和可选的。因此,它只检查MyColumn = MyParamMyParam 是否不为 0。但我们的 DBA 说 OR 会使其变慢,而 db 会受到影响。另一种选择是,

IF MyParam = 0 
SELECT * FROM MyTable WHERE MyColumn = MyParam

这种方法的问题是我们有很多可选参数。所以,我们的查询变得非常非常大。另一种选择是 CASE。

所以你们的建议。我一般说的是Oracle还是SQL Server。

sql-server oracle
  • 3 3 个回答
  • 5377 Views

3 个回答

  • Voted
  1. Best Answer
    SqlZim
    2017-03-22T04:48:12+08:002017-03-22T04:48:12+08:00

    在 sql 服务器中:

    一种选择是动态 sql,另一种是option (recompile).

    使用option (recompile):

    select * from MyTable where MyParam = 0 or MyColumn = MyParam option (recompile);
    

    动态sql示例:

    declare @sql nvarchar(max);
    
    if nullif(@MyParam,0) is not null
      begin;
      set @sql = 'select * from MyTable where MyColumn=@MyParam;'
      exec sp_exeuctesql @sql, '@MyParam int', @MyParam;
      end;
    else 
      begin;
      set @sql = 'select * from MyTable;'
      exec sp_exeuctesql @sql;
      end;
    

    参考:

    • 参数嗅探、嵌入和重新编译选项 - Paul White
    • 动态搜索条件 - Erland Sommarskog
    • 包罗万象的查询 - Gail Shaw
    • 更新的“厨房水槽”示例 - Aaron Bertand
    • 5
  2. Jonathan Fite
    2017-03-22T04:54:33+08:002017-03-22T04:54:33+08:00

    我刚刚在我的环境中针对 AdventureWorks 进行了测试,发现 CASE 方法效果最好。使用 OR 方法使引擎使用聚集索引,而 CASE 语句让它使用非聚集索引。

    所以你的查询可能看起来像这样。

    SELECT *
    FROM MyTable
    WHERE CASE WHEN @MyParam = 0 THEN 1
               WHEN MyColumn = @MyParam THEN 1
               ELSE 0
               END = 1
    

    但是,如果您说有很多参数,那么无论如何您都不太可能使用索引。所以你可能会不管它。我的测试是针对一个简单的查询。

    • 4
  3. AnoE
    2017-03-22T07:23:23+08:002017-03-22T07:23:23+08:00

    SELECT * FROM MyTable WHERE MyParam = 0 OR MyColumn = MyParam

    但是我们的 DBA 说 OR 会使它变慢并且 db 会受到影响。

    这有几个缺陷:

    • 编程世界,尤其是 DB(A) 世界充斥着这样的格言,这些格言令人作呕。“永远不要使用NOT EXISTS,永远不要使用NOT IN,避免这个,避免那个,你必须不惜一切代价做XYZ,不惜一切代价避免OR”等等。这些事情的问题在于,对于特定 RDBMS 的特定版本,它们可能在某个时间点是正确的,并且通常对于该特定 RDBMS 版本的特定参数设置子集是正确的。
    • 这在精神上就像在知道有什么需要优化之前进行优化。唯一完全显而易见的是,您现在在此声明上使用了更多时间(通过思考、询问 SE 等)。所以成本已经上涨了。声明本身是否“坏”甚至没有显示出来,如果它真的是“坏”,甚至没有人证明它已经坏到需要采取行动。

    所以,在这种情况下你应该做什么:创建一个测试用例,然后做一个基准测试。没有什么可以帮助你。

    对于您的特定情况:

    • 理论上,数据库可以优化语句并识别问题;然后它可能几乎和你以不同的方式做的一样快。
    • 开销可以忽略不计,完全没有价值大惊小怪。一个端到端需要 1000 毫秒的请求可能需要多花 1 毫秒,还有一大块值得优化的代码需要另外 999 毫秒。浪费你一分钟的时间来打扰这些事情可能太多了。
    • 另一方面,这个问题可能会对您的表现产生巨大影响。

    做一个基准;进行测试;评估数据库执行统计等。那么你肯定会知道的。

    • 3

相关问题

  • ORDER BY 使用文本列的自定义优先级

  • 舒服的sqlplus界面?[关闭]

  • 如何在数据库中找到最新的 SQL 语句?

  • 如何使用正则表达式查询名称?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve