1. 程式人生 > >如何讓in/exists 子查詢(半連線)作為驅動表?

如何讓in/exists 子查詢(半連線)作為驅動表?

一哥們問我,怎麼才能讓子查詢作為驅動表? SQL如下:

select  rowid rid
   from its_car_pass7 v
  where 1 = 1
    and pass_datetime >=
        to_date('2013-07-06 :17:46:04', 'yyyy-mm-dd hh24:mi:ss')
    and pass_datetime <=
        to_date('2013-07-06 :18:46:06', 'yyyy-mm-dd hh24:mi:ss')
    and v.pass_device_unid in
        (select unid
           from its_base_device
          where dev_bay_unid in ('01685EFE4658C19D59C4DDAAEDD37393')
            and dev_type = '1'
            and dev_chk_flag = '1'
            and dev_delete_flag = 'N')
  order by v.pass_datetime asc 
 /

執行計劃如下:

Execution Plan
----------------------------------------------------------
Plan hash value: 3634433140

--------------------------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name               | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                    |     1 |   111 |     2  (50)| 00:00:01 |       |       |
|   1 |  SORT ORDER BY                |                    |     1 |   111 |     2  (50)| 00:00:01 |       |       |
|   2 |   NESTED LOOPS                |                    |       |       |            |          |       |       |
|   3 |    NESTED LOOPS               |                    |     1 |   111 |     1   (0)| 00:00:01 |       |       |
|   4 |     PARTITION RANGE SINGLE    |                    |     1 |    39 |     1   (0)| 00:00:01 |  1284 |  1284 |
|*  5 |      INDEX SKIP SCAN          | IDX_VT7_DEVICEID   |     1 |    39 |     1   (0)| 00:00:01 |  1284 |  1284 |
|*  6 |     INDEX UNIQUE SCAN         | PK_ITS_BASE_DEVICE |     1 |       |     0   (0)| 00:00:01 |       |       |
|*  7 |    TABLE ACCESS BY INDEX ROWID| ITS_BASE_DEVICE    |     1 |    72 |     0   (0)| 00:00:01 |       |       |
--------------------------------------------------------------------------------------------------------------------

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

   5 - access("PASS_DATETIME">=TO_DATE(' 2013-07-06 17:46:04', 'syyyy-mm-dd hh24:mi:ss') AND
              "PASS_DATETIME"<=TO_DATE(' 2013-07-06 18:46:06', 'syyyy-mm-dd hh24:mi:ss'))
       filter("PASS_DATETIME">=TO_DATE(' 2013-07-06 17:46:04', 'syyyy-mm-dd hh24:mi:ss') AND
              "PASS_DATETIME"<=TO_DATE(' 2013-07-06 18:46:06', 'syyyy-mm-dd hh24:mi:ss'))
   6 - access("V"."PASS_DEVICE_UNID"="UNID")
   7 - filter("DEV_BAY_UNID"='01685EFE4658C19D59C4DDAAEDD37393' AND "DEV_TYPE"='1' AND
              "DEV_DELETE_FLAG"='N' AND "DEV_CHK_FLAG"='1')


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
     110973  consistent gets
          0  physical reads
          0  redo size
      47861  bytes sent via SQL*Net to client
       1656  bytes received via SQL*Net from client
        105  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
       1560  rows processed

這裡我們就不管統計資訊是否準確了,也不管SQL優化的問題,就單單討論哥們問的問題吧。

那哥們說,怎麼才能讓子查詢作為驅動表呢?他自己試了很多方法就是搞不定。 那我們來親自搞搞吧

explain plan for   select  rowid rid
   from its_car_pass7 v
  where 1 = 1
    and pass_datetime >=
        to_date('2013-07-06 :17:46:04', 'yyyy-mm-dd hh24:mi:ss')
    and pass_datetime <=
        to_date('2013-07-06 :18:46:06', 'yyyy-mm-dd hh24:mi:ss')
    and v.pass_device_unid in
        (select unid
           from its_base_device
          where dev_bay_unid in ('01685EFE4658C19D59C4DDAAEDD37393')
            and dev_type = '1'
            and dev_chk_flag = '1'
            and dev_delete_flag = 'N')
  order by v.pass_datetime asc 
 /

執行計劃如下

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(NULL, NULL, 'ADVANCED -PROJECTION'));

-----------------------------------------------------------
Plan hash value: 2191740724
---------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name               | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                    |     1 |   111 |  2092K  (1)| 06:58:26 |       |       |
|   1 |  NESTED LOOPS                        |                    |       |       |            |          |       |       |
|   2 |   NESTED LOOPS                       |                    |     1 |   111 |  2092K  (1)| 06:58:26 |       |       |
|   3 |    PARTITION RANGE SINGLE            |                    |     1 |    39 |  2092K  (1)| 06:58:26 |  1284 |  1284 |
|   4 |     TABLE ACCESS BY LOCAL INDEX ROWID| ITS_CAR_PASS7      |     1 |    39 |  2092K  (1)| 06:58:26 |  1284 |  1284 |
|*  5 |      INDEX RANGE SCAN                | IDX_VT7_DATETIME   |     1 |       |  6029   (1)| 00:01:13 |  1284 |  1284 |
|*  6 |    INDEX UNIQUE SCAN                 | PK_ITS_BASE_DEVICE |     1 |       |     0   (0)| 00:00:01 |       |       |
|*  7 |   TABLE ACCESS BY INDEX ROWID        | ITS_BASE_DEVICE    |     1 |    72 |     0   (0)| 00:00:01 |       |       |
---------------------------------------------------------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$5DA710D3
   4 - SEL$5DA710D3 / [email protected]$1
   5 - SEL$5DA710D3 / [email protected]$1
   6 - SEL$5DA710D3 / [email protected]$2
   7 - SEL$5DA710D3 / [email protected]$2
 
Outline Data
-------------
 
  /*+
      BEGIN_OUTLINE_DATA
      NLJ_BATCHING(@"SEL$5DA710D3" "ITS_BASE_DEVICE"@"SEL$2")
      USE_NL(@"SEL$5DA710D3" "ITS_BASE_DEVICE"@"SEL$2")
      LEADING(@"SEL$5DA710D3" "V"@"SEL$1" "ITS_BASE_DEVICE"@"SEL$2")
      INDEX(@"SEL$5DA710D3" "ITS_BASE_DEVICE"@"SEL$2" ("ITS_BASE_DEVICE"."UNID"))
      INDEX_RS_ASC(@"SEL$5DA710D3" "V"@"SEL$1" ("ITS_CAR_PASS7"."PASS_DATETIME"))
      OUTLINE(@"SEL$2")
      OUTLINE(@"SEL$1")
      UNNEST(@"SEL$2")
      OUTLINE_LEAF(@"SEL$5DA710D3")
      FIRST_ROWS
      DB_VERSION('11.2.0.3')
      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
      IGNORE_OPTIM_EMBEDDED_HINTS
      END_OUTLINE_DATA
  */
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   5 - access("PASS_DATETIME">=TO_DATE(' 2013-07-06 17:46:04', 'syyyy-mm-dd hh24:mi:ss') AND 
              "PASS_DATETIME"<=TO_DATE(' 2013-07-06 18:46:06', 'syyyy-mm-dd hh24:mi:ss'))
   6 - access("V"."PASS_DEVICE_UNID"="UNID")
   7 - filter("DEV_BAY_UNID"='01685EFE4658C19D59C4DDAAEDD37393' AND "DEV_TYPE"='1' AND "DEV_DELETE_FLAG"='N' AND 
              "DEV_CHK_FLAG"='1')


TMD 執行計劃又變了,我們也先別管執行計劃為啥變了,驅動表仍然是 ITS_CAR_PASS7,現在我們來改變驅動表

select /*+ leading([email protected]$2) */ rowid rid
   from its_car_pass7 v
  where 1 = 1
    and pass_datetime >=
        to_date('2013-07-06 :17:46:04', 'yyyy-mm-dd hh24:mi:ss')
    and pass_datetime <=
        to_date('2013-07-06 :18:46:06', 'yyyy-mm-dd hh24:mi:ss')
    and v.pass_device_unid in
        (select unid
           from its_base_device
          where dev_bay_unid in ('01685EFE4658C19D59C4DDAAEDD37393')
            and dev_type = '1'
            and dev_chk_flag = '1'
            and dev_delete_flag = 'N')
  order by v.pass_datetime asc 
 /

Execution Plan
----------------------------------------------------------
Plan hash value: 712001411

-------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                          | Name                     | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                   |                          |     1 |   111 |    25   (4)| 00:00:01 |       |       |
|   1 |  SORT ORDER BY                     |                          |     1 |   111 |    25   (4)| 00:00:01 |       |       |
|*  2 |   TABLE ACCESS BY LOCAL INDEX ROWID| ITS_CAR_PASS7            |     1 |    39 |     2   (0)| 00:00:01 |  1284 |  1284 |
|   3 |    NESTED LOOPS                    |                          |     1 |   111 |    24   (0)| 00:00:01 |       |       |
|*  4 |     TABLE ACCESS BY INDEX ROWID    | ITS_BASE_DEVICE          |     6 |   432 |    12   (0)| 00:00:01 |       |       |
|*  5 |      INDEX RANGE SCAN              | IDX_DEVICE_DEV_BAY_UNID  |     7 |       |     1   (0)| 00:00:01 |       |       |
|   6 |     PARTITION RANGE SINGLE         |                          |    44M|       |     2   (0)| 00:00:01 |  1284 |  1284 |
|*  7 |      INDEX RANGE SCAN              | IDX_VT7_PASS_DEVICE_UNID |    44M|       |     2   (0)| 00:00:01 |  1284 |  1284 |
-------------------------------------------------------------------------------------------------------------------------------

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

   2 - filter("PASS_DATETIME">=TO_DATE(' 2013-07-06 17:46:04', 'syyyy-mm-dd hh24:mi:ss') AND
              "PASS_DATETIME"<=TO_DATE(' 2013-07-06 18:46:06', 'syyyy-mm-dd hh24:mi:ss'))
   4 - filter("DEV_TYPE"='1' AND "DEV_DELETE_FLAG"='N' AND "DEV_CHK_FLAG"='1')
   5 - access("DEV_BAY_UNID"='01685EFE4658C19D59C4DDAAEDD37393')
   7 - access("V"."PASS_DEVICE_UNID"="UNID")


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      18645  consistent gets
        130  physical reads
          0  redo size
      47861  bytes sent via SQL*Net to client
       1657  bytes received via SQL*Net from client
        105  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
       1560  rows processed


驅動表改了之後,邏輯讀從11W降低為1.8W

相關推薦

如何in/exists 查詢(連線)作為驅動

一哥們問我,怎麼才能讓子查詢作為驅動表? SQL如下: select rowid rid from its_car_pass7 v where 1 = 1 and pass_datetime >= to_date('2013-07-

關於所使用的spark版本中的spark sql不支援existsin查詢語句的解決方案記錄

stackoverflow上一篇很好的問題解答解決方法: A table holds the rows that make some predicate (statement parameterized by column names) true: The DBA

關於T-SQL中exists或者not exists查詢的“偽優化”的做法

png tro ges width 9.png 當前 color 盡心 alt 問題起源 在使用t-sql中的exists(或者not exists)子查詢的時候,不知道什麽時候開始,發現一小部分人存在一種“偽優化”的一些做法,並且向不明真相

in查詢陷阱

們的 goods inner cnblogs 目的 針對 欄目 exp com in 型子查詢引出的陷阱 select goods_id from goods where cat_id in (1,2,3) 直接用id,不包含子查詢,不會中陷阱 題: 在ecshop商城表中

mysql in查詢陷阱

秒級 tab lai sql 一對一 語句 lec 掃描 主鍵 現在有兩個表,table1和table2,table1有1千萬數據(id 主鍵索引),table2有三條數據(uid字段 3,5,7); select * from table1 where id in

EXISTS查詢問題

今天SQL Server課講到帶有EXISTS運算子的子查詢 第一段的簡介是: 存在性子查詢使用EXISTS運算子,EXISTS子查詢並不返回任何資料,只產生邏輯值TRUE或FALSE。由於存在性子查詢只是檢測是否存在符合條件的記錄,因此不需要列出具體的列名,選擇列幾乎都由(*)組成 給出的

mysql在把子查詢結果作為刪除中資料的條件,mysql不允許在查詢的同時刪除原資料

** 目標表和原表一致 MYSQL不支援如此操作 資料庫不能邊查詢邊刪除 ** delete from push_msg_overview where id in ( select id from push_msg_overview where pus

MySQL基礎知識(四)——查詢連線

一.子查詢 先建立一張商品表,後續對其進行操作。 # 建立一個商品表,商品id:goods_id 商品名稱:goods_name 商品分類:goods_cate # 商品品牌:brand_name 商品價格:goods_price 是否上架:is_show 是否已售空:is_saleof

mysql---where查詢、form查詢exists查詢

create table article(article_id int(3),article_title varchar(50),article_content text,article_comments int(3),articlecategory_id int(3) ); insert into arti

mysql not in null 查詢問題

今天寫了一個sql: SELECT * from tableA a where a.mobile not in (select b.mobile from tableB b); 在本地的一個測試資料庫執行能查出資料,然後放外網查詢就沒有資料。 經過確定,外網是應該查出資料的,

MySQL查詢join連線union

where型子查詢 指把內層查詢的結果作為外層查詢的比較條件,典型題:查詢id最大,最貴商品 如果where 列 =(內層sql),則內層sql返回的必須是單行單列,單個值; 如果where 列 in(內層sql),則內層sql只返回單列,可以多行。   --查出本網站

Mysql中exists查詢語句的使用,取出每組中最高的前n名的資訊

一、準備測試的表和資料 create table cat( id int not null auto_increment primary key, cat_id int, value int,

SQL優化案例--使用LEFT JOIN替換NOT EXISTS查詢

轉載  在一些業務場景中,會使用NOT EXISTS語句確保返回資料不存在於特定集合,部分同事會發現NOT EXISTS有些場景效能較差,甚至有些網上謠言說”NOT EXISTS不走索引”,哪對於NOT EXISTS語句,我們如何優化呢?##=================

查詢連線

有如下兩張表:部門表和教師表 1、查詢出招生部門所有男老師姓名(子查詢放在where語句中) select tname, deptno from teacher where gender='男' and deptno in (select de

mysql的查詢查詢連線查詢

一、mysql查詢的五種子句 where(條件查詢)、having(篩選)、group by(分組)、order by(排序)、limit(限制結果數) 1、where常用運算子: 比較運算子 > , < ,= , != (< >),>= ,

JOIN與EXISTS(查詢)的效率研究

使用MySQL提供的Sample資料庫Sakila 現將profiling開啟,用來一會檢視sql執行時間 set profiling=1;  exists 子查詢與 join聯接效率的對比,功能:檢視沒有演員的電影 EXPLAIN SELECT film_id,

in查詢引出的陷阱

在開發商城的時候,核心有一個goods表和category表,category中有多級分類。假設有一個父分類為6,這個父分類中沒有商品,商品都在子分類中,那麼要查詢分類為6的商品,如果我們使用in型子查詢,會使用下面的sql。 select * from

查詢連線使用指南

 子查詢就是查詢中又巢狀的查詢,巢狀的級數隨各資料庫廠商的設定而有所不同,一般最大巢狀數不超過15級,實際應用中,一般不要超過2級,否則程式碼難以理解.一般來說,所有巢狀子查詢都可改寫為非巢狀的查詢,但是這樣將導致程式碼量增大.子查詢就如遞迴函式一樣,有時侯使用起來能達到事半

處理mysql使用in關鍵字查詢1317錯誤

         Error 1317 mysql query execution interrupted  訊息內容:查詢執行被中斷(資料庫直接掛起) 1. 現象: (1)在PHP程式中使用子查詢語句,導致Mysql自動“掛起”,即資料庫“卡死”,程式不能正常執行 (2

MySQL Execution Plan--NOT EXISTS查詢優化

次數 .com HERE 毫秒 存在 數據 統計 圖片 兩個 在很多業務場景中,會使用NOT EXISTS語句來確保返回數據不存在於特定集合,部分場景下NOT EXISTS語句性能較差,網上甚至存在謠言"NOT EXISTS無法走索引"。 首先需要明確的是:索引不是萬能的