我不是在寻找以下的优化,只是一个解释.我有这样的疑问:

SELECT COUNT(LARGE_A.id_a), SUM(LARGE_A.b_integer)
FROM LARGE_A
INNER JOIN MEDIUM_A ON LARGE_A.id_a = MEDIUM_A.id
INNER JOIN MEDIUM_B ON LARGE_A.id_b = MEDIUM_B.id
WHERE
    MEDIUM_A.a_varchar2 LIKE 'Example%' AND
    EXTRACT(YEAR FROM MEDIUM_B.a_datetime) = 2000 AND
    LARGE_A.a_integer BETWEEN 0 AND 1000;

属性的类型写在它们的名称中.ID是整数.表LARGE_A有1 000 000行,中等行各有LARGE_A 000行.ID是主键,但是表LARGE_A具有复合键(id_a, id_b).

然后我得到了下面的执行计划,取自V$SQL视图,因为AutoTrack对这一点撒谎.

SELECT STATEMENT                        
|SORT AGGREGATE                         
||HASH JOIN                             
|||NESTED LOOPS                         
||||NESTED LOOPS                        
|||||STATISTICS COLLECTOR               
||||||NESTED LOOPS                      
|||||||TABLE ACCESS FULL                LARGE_A
|||||||TABLE ACCESS BY INDEX ROWID      MEDIUM_A
||||||||INDEX UNIQUE SCAN               PK(MEDIUM_A)
|||||INDEX UNIQUE SCAN                  PK(MEDIUM_B)
||||TABLE ACCESS BY INDEX ROWID         MEDIUM_B
|||TABLE ACCESS FULL                    MEDIUM_B

Pk表示括号中的表的主键(一个整数)上的非聚集索引.我在这里不用IOT.

为什么优化器首先从索引PK(MEDIUM_B)逐个查询记录,然后使用ROWID获取其余行,然后再次运行全表扫描?

推荐答案

你看到的是full计划,而不是actual计划(在v$sql中,full_plan_hash_valueplan_hash_value之间的区别).自12c以来,甲骨文有了适应性计划,使其能够在飞行途中从一个计划更改到另一个计划,如果它在运行时发现自己的基数猜测是错误的.FULL计划提供了两种 Select --散列连接+对表B的完全扫描,或者嵌套循环+对表B的索引访问.这完全取决于它从表A获得多少行来判断哪个是最佳计划.

你可以这样看得最好:

EXPLAIN PLAN FOR ....
/
SELECT * FROM TABLE(dbms_xplan.display(format=>'ADAPTIVE'))
/

您将在禁用的计划行旁边看到-个标记,这是默认情况下不会使用的标记...但它们仍然是计划的一部分,因此如果Oracle在执行中期决定切换,它可以启用这些行并禁用原始默认设置.要查看代码在运行时实际使用了什么,您必须通过获取v$session.sql_id / sql_child_number来观察它,然后执行以下操作:

SELECT * FROM TABLE(dbms_xplan.display_cursor([sqlid],[childnumber]))

/

Sql相关问答推荐

基于前面行的值:当x&>2时重复1,当连续3行x=0时则重复0

在SQL中使用类别值将行转置为列

两个不同星期的销售额,不加成一行

Select 非重复值并按条件排除行

查询页面推荐

在SQL中为两个日期之间的每个日期添加行

在Athena中使用regexp提取括号前的字符串值

Postgres jsonpath运算符的变量替换,如_regex?

在SQL查询中查找客户端的最短日期比较列和多行

获取主表条目,其中最新的辅助条目是 6 个月前

如何 for each id创建长度等于id长度的不同日期序列?

没有调用子查询的嵌套 JOIN语法是什么?

SQL Server - 复杂场景 - 比较状态并填充值到后续行

如何根据共同列值从两个表中包含列,但只包含左表中的行

带有数组输入参数的Snowflake UDF优化

如何通过CROSS APPLY获取多级嵌套JSON属性的值?

自动生成计算频率的列

Select 字段,除非另一个字段包含重复项

如何根据另一列对行值进行分组?

Select 随机行,使得列子组的组合是唯一的