1

我有这个非常简单的查询,通过 rowid 执行过滤和连接。

SELECT *
FROM  BOOKING.BOOKING_GRID BG,
  BOOKING.BOOKING_STATES BS
WHERE BG.hotel=128
AND BS.ROWID =BG.BOOKINGSTATE;

当我解释计划时,我得到:

PLAN_TABLE_OUTPUT                                                                                                                                                                                                                                                                                          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1597031677                                                                                                                                                                                                                                                                                  

--------------------------------------------------------------------------------------------------                                                                                                                                                                                                           
| Id  | Operation          | Name                | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |                                                                                                                                                                                                           
--------------------------------------------------------------------------------------------------                                                                                                                                                                                                           
|   0 | SELECT STATEMENT   |                     |  6137K|  1041M|       |  1763K  (1)| 05:48:27 |                                                                                                                                                                                                           
|*  1 |  HASH JOIN         |                     |  6137K|  1041M|   538M|  1763K  (1)| 05:48:27 |                                                                                                                                                                                                           
|*  2 |   INDEX UNIQUE SCAN| BOOKING_GRIDPK      |  6137K|   468M|       |   547K  (1)| 01:48:05 |                                                                                                                                                                                                           
|*  3 |    INDEX RANGE SCAN| BOOKING_GRID_INDEX5 |  6137K|       |       | 90388   (1)| 00:17:52 |                                                                                                                                                                                                           
|   4 |   TABLE ACCESS FULL| BOOKING_STATES      |   158M|    14G|       |   365K  (2)| 01:12:14 |                                                                                                                                                                                                           
--------------------------------------------------------------------------------------------------                                                                                                                                                                                                           

Predicate Information (identified by operation id):                                                                                                                                                                                                                                                          
---------------------------------------------------                                                                                                                                                                                                                                                          

   1 - access("BS".ROWID="BG"."BOOKINGSTATE")                                                                                                                                                                                                                                                                
   2 - access("BG"."HOTEL"=128)                                                                                                                                                                                                                                                                              
   3 - access("BG"."HOTEL"=128)     

BOOKING_GRID 的索引是:

BOOKING BOOKING_GRIDPK  UNIQUE  VALID   IOT - TOP   N   NO      NO  HOTEL, DAY, BOOKINGSTATE
BOOKING BOOKING_GRID_UNIQ   UNIQUE  VALID   NORMAL  N   NO      NO  HOTEL, DAY, BOOKING, VALIDITYSTART
BOOKING BOOKING_GRID_INDEX5 NONUNIQUE   VALID   NORMAL  N   NO      NO  HOTEL, BOOKINGSTATUS, ISDAYUSE, DAY
BOOKING BOOKING_GRID_INDEX7 NONUNIQUE   VALID   NORMAL  N   NO      NO  HOTEL, BOOKING, VALIDITYSTART
BOOKING BOOKING_GRID_INDEX10    NONUNIQUE   VALID   NORMAL  N   NO      NO  HOTEL, ISDAYUSE, BOOKINGSTATUS, DAY

BOOKING_STATES 的索引是:

BOOKING BOOKING_STATES_PK   UNIQUE  VALID   NORMAL  N   NO      NO  HOTEL, BOOKING, VALIDITYSTART   
BOOKING BOOKING_STATES_INDEX2   NONUNIQUE   VALID   NORMAL  N   NO      NO  HOTEL, YIELDROOMTYPE, BOOKEDROOMTYPE, ROOMTYPE  
BOOKING BOOKING_STATES_BOOKING  NONUNIQUE   VALID   NORMAL  N   NO      NO  HOTEL, BOOKING, BOOKINGSTATUS   
BOOKING BOOKING_NOSEGMENT_INDEX NONUNIQUE   VALID   FUNCTION-BASED NORMAL   N   NO  ENABLED NO  SYS_NC00034$    TO_NUMBER(DECODE(TO_CHAR("MARKETSEGMENT"),NULL,DECODE("BOOK",0,NULL,TO_CHAR(DECODE("ISDAYUSE",'N',DECODE("ISSHARED",'N',DECODE("BOOKINGSTATUS",'B',"HOTEL"*10000+LEAST("DEPARTURE","VALIDITYEND"),'I',"HOTEL"*10000+LEAST("DEPARTURE","VALIDITYEND"),'W',"HOTEL"*10000+LEAST("DEPARTURE","VALIDITYEND"))))))))
BOOKING BOOKING_NORATE_CODE_INDEX   NONUNIQUE   VALID   FUNCTION-BASED NORMAL   N   NO  ENABLED NO  SYS_NC00033$    TO_NUMBER(DECODE(TO_CHAR("RATECODE"),NULL,DECODE("BOOK",0,NULL,TO_CHAR(DECODE("ISDAYUSE",'N',DECODE("ISSHARED",'N',DECODE("BOOKINGSTATUS",'B',"HOTEL"*10000+LEAST("DEPARTURE","VALIDITYEND"),'I',"HOTEL"*10000+LEAST("DEPARTURE","VALIDITYEND"),'W',"HOTEL"*10000+LEAST("DEPARTURE","VALIDITYEND"))))))))
BOOKING BOOKING_NOBOOKINGTYPE_INDEX NONUNIQUE   VALID   FUNCTION-BASED NORMAL   N   NO  ENABLED NO  SYS_NC00032$    TO_NUMBER(DECODE(TO_CHAR("BOOKINGTYPE"),NULL,DECODE("BOOK",0,NULL,TO_CHAR(DECODE("ISDAYUSE",'N',DECODE("ISSHARED",'N',DECODE("BOOKINGSTATUS",'B',"HOTEL"*10000+LEAST("DEPARTURE","VALIDITYEND"))))))))
BOOKING BOOKING_STATES_BOOKING_TYPE NONUNIQUE   VALID   NORMAL  N   NO      NO  HOTEL, BOOKINGTYPE, ISDAYUSE, BOOKINGSTATUS 
BOOKING BOOKING_STATES_CANCEL_INDEX NONUNIQUE   VALID   FUNCTION-BASED NORMAL   N   NO  ENABLED NO  SYS_NC00035$, SYS_NC00036$  DECODE("BOOKINGSTATUS",'c',"HOTEL",'C',"HOTEL")
BOOKING BOOKING_STATES_CANCEL_INDEX NONUNIQUE   VALID   FUNCTION-BASED NORMAL   N   NO  ENABLED NO  SYS_NC00035$, SYS_NC00036$  DECODE("BOOKINGSTATUS",'c',"CANCELREASON",'C',"CANCELREASON")

我不明白两件事:

  1. 为什么甲骨文会在过滤酒店 = 128 之前决定加入更快?
  2. 为什么在可以使用“TABLE ACCESS BY USER ROWID”时使用散列连接

奇怪的是,当我使用 hotel=201 运行相同的请求时,它完全没问题:

PLAN_TABLE_OUTPUT                                                                                                                                                                                                                                                                                          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 4251203092                                                                                                                                                                                                                                                                                  

---------------------------------------------------------------------------------------------------                                                                                                                                                                                                          
| Id  | Operation                   | Name                | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                                                                                                          
---------------------------------------------------------------------------------------------------                                                                                                                                                                                                          
|   0 | SELECT STATEMENT            |                     |   591K|   100M|   643K  (1)| 02:07:12 |                                                                                                                                                                                                          
|   1 |  NESTED LOOPS               |                     |   591K|   100M|   643K  (1)| 02:07:12 |                                                                                                                                                                                                          
|*  2 |   INDEX UNIQUE SCAN         | BOOKING_GRIDPK      |   591K|    45M| 52686   (1)| 00:10:25 |                                                                                                                                                                                                          
|*  3 |    INDEX RANGE SCAN         | BOOKING_GRID_INDEX5 |   591K|       |  8707   (1)| 00:01:44 |                                                                                                                                                                                                          
|   4 |   TABLE ACCESS BY USER ROWID| BOOKING_STATES      |     1 |    98 |     1   (0)| 00:00:01 |                                                                                                                                                                                                          
---------------------------------------------------------------------------------------------------                                                                                                                                                                                                          

Predicate Information (identified by operation id):                                                                                                                                                                                                                                                          
---------------------------------------------------                                                                                                                                                                                                                                                          

   2 - access("BG"."HOTEL"=201)                                                                                                                                                                                                                                                                              
   3 - access("BG"."HOTEL"=201)  

知道那里发生了什么吗?

谢谢,

雷诺

4

1 回答 1

1

执行路径不同的原因是因为 Oracle 认为 hotel=128 的行大约有 600 万行,但 hotel=201 的行只有 591,000 行。在更大的中间集的情况下,Oracle 选择了散列连接而不是嵌套循环。

我不明白的是:

AND BS.ROWID =BG.BOOKINGSTATE;

您将 Oracle 格式的 ROWID 存储在名为 BOOKINGSTATE 的列中???


好的,鉴于您确认 BOOKINGSTATE 确实包含 Oracle ROWID,这就是为什么我会说您获得的是 HASH JOIN 而不是 NESTED LOOP 连接:

首先,当 Oracle 读取一行时,它不只是一次读取一行,而是一次读取块。因此,要使用 TABLE ACCESS BY USER ROWID 查找进行嵌套循环连接,它将在 BOOKING_GRID 中找到一行,然后使用该 ROWID 读取 BOOKING_STATES 中具有该行的块。问题是,如果稍后在之前已经读取过的块中存在另一行带有 rowid 的行,它将重新读取该块(当然,它可能被缓存)以获取另一行。有点像“打开方块,放一排,关上盒子……然后再打开同一个盒子,再放一排,关上盒子,继续下一个盒子”

另一方面,您的散列连接是: - 对较小集合中的行进行排序(在本例中为 BOOKING_GRID 中的行,其中hotel = 128),将它们放入内存中 - 全表扫描 BOOKING_STATES - 这是踢球者 - 使用多块读取. 它一次读取许多块并处理块中的所有行,而无需稍后重新读取。这就像“打开盒子,处理盒子中的所有行,然后关闭盒子”。

(有关上述内容的更多详细信息,请查看http://docs.oracle.com/cd/B28359_01/server.111/b28274/optimops.htm,尤其是以下部分:

  • 11.5.1 全表扫描
  • 11.5.3.1 评估块的 I/O,而不是行
  • 11.6.3 嵌套循环连接
  • 11.6.4 哈希连接)

顺便说一句,它使用两个索引执行两次“访问(“BG”。“HOTEL”=128)”步骤有点奇怪——BOOKING_GRIDPK 和 BOOKING_GRID_INDEX5 索引是如何定义的?您要求两个表中的所有列,但该计划从未触及 BOOKING_GRID 表。)

于 2013-09-04T16:37:15.243 回答