【问题标题】:Case clause execution procedure案例条款执行程序
【发布时间】:2023-03-28 18:29:02
【问题描述】:

您好,我有一个非常慢的 SQL。

select case when (value=1) 
then (select <Some Math Logic> from table where table.id=table_2.id) 
else 'false' end 
from table_2 where <where clause>

我想知道的是 case 子句是如何工作的..??

select &lt;Some Math Logic&gt; from table 的部分正在处理巨大的表集。

在 Java 中,我们在 if 语句中看到了这一点

if(condition_1==true) 
{return output;} 
else 
{return false;}

如果 if 语句为假,那么它里面的部分永远不会被处理,那么我想知道的是它在 oracle SQL 中是否也一样。

它是否适用于以下逻辑..??

  • 检查案例条件
  • 如果为真,则在输出中处理
  • else 处理其他输出。

还是采用以下逻辑:

  • 预处理所有子查询
  • 检查案例条件
  • 如果为真,则显示在输出中
  • else 显示其他输出。

请帮忙

编辑:伙计们,我不想调整上面显示的查询......这只是一个虚拟的。

我需要知道的是case子句是如何一步一步工作的。

如果有人对此有一些意见,请分享

【问题讨论】:

  • 您的子查询与主查询有何关联?
  • 有连接子句不能编辑查询..,.
  • 据我所知,案例逻辑按照您在 java 中的示例工作。当你将 (value = 1) 切换到总是返回 false 的东西时会发生什么?还是慢吗?也许问题出在其他地方。
  • 你试过explain plan吗?我猜会发生第三种情况:查询可能被重写为 tabletable_2 在其 id 列上的连接。这是两张桌子上的一个选择。对于每个结果行,要么评估&lt;some math logic&gt;,要么使用false - 取决于value。如果可能,在两个 id 列上设置索引。
  • value 来自哪里?是 TABLE_2 上的参数还是列?

标签: sql performance oracle query-performance


【解决方案1】:

这能解决您的问题吗?

SELECT
   COALESCE(<Some Math Logic>, 'false')
FROM table_2 T2
    LEFT JOIN table T
        ON T.Id = T2.Id
           and T2.value = 1
WHERE <where clause>

【讨论】:

  • 我不想要查询的调优,我只想要子句的执行计划......无论如何,COALESCE 是如何工作的......??它由谁来工作意味着一次走一步
【解决方案2】:

好像逻辑和java里的一模一样。

我使用以下逻辑来测试您的场景:

我创建了一个如下所示的虚拟函数,它只会在 dbms_output 上写入一些内容并仅返回 10。

CREATE OR REPLACE
  FUNCTION DISP_MSG
    RETURN VARCHAR2
  AS
    ret_val VARCHAR2(20):='10';
  BEGIN
    dbms_output.enable;
    dbms_output.put_line('executed');
    RETURN ret_val;
  END DISP_MSG;

然后我创建了一个匿名块来测试它:

DECLARE
  var VARCHAR2(100);
BEGIN
  SELECT CASE WHEN (1!=1) THEN DISP_MSG ELSE '1' END INTO var FROM dual;
  dbms_output.put_line('j = '||var);
END;

输出:

j = 1

但是当我尝试以下操作时:

DECLARE
  var VARCHAR2(100);
BEGIN
  SELECT CASE WHEN (1=1) THEN DISP_MSG ELSE '1' END INTO var FROM dual;
  dbms_output.put_line('j = '||var);
END;

输出:

执行

j = 10

所以很清楚什么是执行逻辑

【讨论】:

  • 我不认为这能证明什么——DISP_MSG 函数就像一个常量——它会做一个“FAST DUAL”,更重要的是,你将一个常量与一个常量而不是一个值进行比较从表中,尝试查看此查询的执行计划:select case when dummy='Y' then (select count(*) from user_objects) else 0 end from dual。当我检查这个时,我发现即使 dummy 始终是“X”,它也有“TABLE ACCESS FULL”
  • 你没有得到这个问题......这不是关于全面扫描......用户已经明确表示他只想知道执行过程是什么......“编辑:伙计们,我不想调整上面显示的查询......这只是一个虚拟的。我需要知道的是 case 子句如何逐步工作。如果有人对此有一些意见,请分享“
  • 我明白,我只是说你没有证明任何事情,因为如果有 - 在执行计划中 - 对 select 语句中的表进行全表扫描(根据你的答案永远不会被评估)那么你的答案有问题......
【解决方案3】:

好问题。您需要查看执行计划才能确定。数据库引擎可以免费使用它认为合适的任何算法,只要它能够为您提供所需的结果。

它甚至可以外连接table 以获得预期值 = 1 的结果。或者它可以运行从表中选择并将结果存储到一个临时表中,它可以在运行主查询时进行扫描。

然而,最有可能的是,它为 value = 1 的每一行运行子查询。如果没有看到计划就很难判断。

这也取决于 .你在服用聚合体吗?如果是这样,真正的连接可能是不可能的,它可能必须重新计算每一行的答案。如果它正在查看表格行上的值,那么它可能能够优化它。

如果去掉 case 语句,整个查询是否执行得更快?想要确保您正在分析正确的子查询。

【讨论】:

  • 我认为在这种情况下不需要计划。与 select 子句中的大量数据相关的子查询。我想这说明了一切。
  • 不,它并没有说明一切。首先,我见过两个查询独立运行快速的情况,但是将它们合并到一个带有连接或子查询或其他查询的查询中,它们表现不佳。其次,OP没有要求代码。他问它将遵循哪个计划。所以我建议他向 Oracle 索要一个执行计划。
猜你喜欢
  • 2017-06-23
  • 1970-01-01
  • 2012-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多