如何讓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不支援exists和in等子查詢語句的解決方案記錄
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無法走索引"。 首先需要明確的是:索引不是萬能的