Oracle表連線操作——Nest Loop Join(巢狀迴圈)
關係型資料庫並不是最早出現的資料庫表現形式,之前還存在層次、網狀資料庫結構。隨著關係型資料庫的出現,以資料表的方式進行資訊留存的方案迅速發展起來。關係型資料庫的重要元素包括資料表和表連線,藉助各種型別的表連線,可以將平鋪直敘的資訊加以組裝拼接。
在Oracle資料庫中,應對不同的連線情況和資料特徵,資料庫CBO會生成不同的執行計劃和連線操作。本篇介紹各種連線中的一種——Nest Loop Join巢狀迴圈。
1、巢狀迴圈原理
巢狀迴圈Nest Loop Join是一種古老的連線方式。SQL中的連線,本質上就是將兩個資料集合依據連線條件進行匹配操作。Nest Loop Join就是通過兩層迴圈手段進行依次的匹配操作,最後返回結果集合。SQL
Nest Loop Join的操作過程很簡單,很想我們最簡單的排序檢索演算法,兩層迴圈結構。進行連線的兩個資料集合(資料表)分別稱為外側表(驅動表)和內測表(被驅動表)。首先處理外側表中每一行符合條件的資料,之後每一行資料和內測表進行連線匹配操作。最後可以獲取到結果集合。
具體來說,Nest Loop Join的執行過程如下:
ü Oracle CBO首先將一系列的連線關係,拆分為若干層的Nest Loop Join,確定連線順序。如a.field1=b.field1 and b.field2=c.field2,就可以組織成表A和表B先進行nest loop join操作,之後操作的結果集合再與資料表C進行nest loop join操作。所以,我們檢視到的連線操作,通常都是分層次的;
ü 在確定每次Nest Loop Join的兩端物件之後,確定外側連線表和內側連線表。將外側連線表作為連線驅動表,根據SQL中對驅動表的連線條件,進行篩選。最後獲取到驅動表資料集合;
ü 從驅動表每條記錄入手,檢索內側表記錄,獲取符合連線條件的記錄。形成連線行;
注意:此處有兩個需要注意的問題。其一是驅動表的確定。另一個就是檢索內側表的方法。這兩個問題在CBO時代的回答都是成本問題,Oracle通過成本試算獲取到。對Nest Loop Join而言,條件列、連線列上的索引是會很大程度上影響執行計劃的。
下面是一個SQL語句的執行計劃,由於CBO操作的複雜性,本SQL使用hint來進行強制的Nest Loop
SQL> create table tabs as select * from dba_tables;
Table created
SQL> create table cols as select owner,table_name, column_name, data_type from dba_tab_cols;
Table created
SQL> create index idx_tabs_owner on tabs(owner);
Index created
SQL> create index idx_cols_name on cols(table_name);
Index created
SQL> set linesize 10000;
SQL> set pagesize 1000;
SQL> explain plan for select /*+use_nl(tabs,cols) */* from tabs, cols where tabs.table_name=cols.tab
le_name and tabs.owner='SCOTT';
已解釋。
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 2834620917
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1355 | 381K| 360 (0)| 00:00:05 |
| 1 | NESTED LOOPS | | | | | |
| 2 | NESTED LOOPS | | 1355 | 381K| 360 (0)| 00:00:05 |
| 3 | TABLE ACCESS BY INDEX ROWID| TABS | 117 | 28314 | 9 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | IDX_TABS_OWNER | 117 | | 1 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | IDX_COLS_NAME | 12 | | 2 (0)| 00:00:01 |
| 6 | TABLE ACCESS BY INDEX ROWID | COLS | 12 | 552 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("TABS"."OWNER"='SCOTT')
5 - access("TABS"."TABLE_NAME"="COLS"."TABLE_NAME")
已選擇19行。
在執行計劃中,伴隨著兩個Nest Loop Join。首先,通過條件owner=’SCOTT’,檢索索引idx_tabs_owner,獲取符合條件的rowid列表。之後利用rowid從tabs表中取出結果集合。這個集合就成為第一層Nest Loop Join的外側表(Outer)。
第一層Nest Loop Join的兩端外側表是TABS結果集合,內側表(集合)則是COLS資料表對應的索引IDX_COLS_NAME,進行匹配的條件是table_name相等。第一層Nest Loop Join的結果集合是TABS所有符合條件行欄位,外加上對應COLS資料表的rowid。
第二層Nest Loop Join就是通過獲取到的COLS rowid找到COLS記錄的全部內容。
2、Nest Loop Join檢索圖示
下面通過一張示意,表達在沒有連線列索引的情況下,Nest Loop Join的工作方式。
在沒有索引的情況下,首先Oracle會檢索驅動表外側表(全表掃描),獲取到符合外側表單獨條件的記錄行集合(Row1和Row2)。
之後針對row1和row2,分別對inner表進行全表匹配查詢,就是對每個outer的結果行,要進行inner表的所有塊查詢。最後發現符合條件的row3和row4,將結果返回。
通過圖示,我們也可以發現Nest Loop Join的一個致命缺陷:存在大量的隨機讀。為一個outer行,就需要進行inner表的全表掃描。如果inner表很龐大,那麼這個執行計劃效率可想而知。
3、索引優化與Nest Loop Join
在目前的Oracle執行計劃中,如果inner和outer表均沒有索引等優化方式,而且不包含那些很複雜的連線對應條件,出現Nest Loop Join的機會還是很低的。因為Oracle CBO會選擇其他替代執行計劃(如Hash Join)來參與執行計劃。
在條件列,特別是連線條件列上新增索引,可以大幅度的減少Nest Loop Join的隨機讀。見下圖示意:
如果在inner表(或者outer)的連線條件列上新增索引,在進行Nest Loop Join的時候,Row1/Row2可以直接確定符合連線條件的Inner Table資料行對應的rowid。不需要直接對inner table進行檢索,就可以獲取到rowid了。由於索引對應的體積要遠遠小於Inner Table,所以進行的塊讀取要少很多。
結論:如果確定需要使用巢狀迴圈Nest Loop Join,那麼最好考慮保證連線列上能存在索引物件。這樣可以很大程度上提高Nest Loop Join的連線效率。
相關推薦
Oracle表連線操作——Nest Loop Join(巢狀迴圈)
關係型資料庫並不是最早出現的資料庫表現形式,之前還存在層次、網狀資料庫結構。隨著關係型資料庫的出現,以資料表的方式進行資訊留存的方案迅速發展起來。關係型資料庫的重要元素包括資料表和表連線,藉助各種型別的表連線,可以將平鋪直敘的資訊加以組裝拼接。在Oracle資料庫中,應對不同
MySQL基礎(4)——子查詢(巢狀查詢)、聯結表、組合查詢
本篇主要整理查詢表、聯結表的相關內容。 一、子查詢 MySQL 4.1版本及以上支援子查詢 子查詢:巢狀在其他查詢中的查詢。 子查詢的作用: 1、進行過濾: 例項1:檢索訂購物品TNT2的所有客戶的ID = + 一般,在WHERE
【java面試題】Static Nested Class(巢狀類) 和 Inner Class(內部類)的不同 、final、static
前言: 本來是想總結一下inner class 的用法,但是卻發現這幾位頗為親近。索性一起拉出來溜溜。 寫作目的: 跟 static , final, inner class 搞好關係,以便將來遇見了,就像用if ,else一樣,一清二楚。 文中的術語定義以java language spec為準。 先想想
java中的內部類(巢狀類)
1.內部類:定義在另一個類裡面的類 外部類:包含內部類的類 2.內部類的名字不允許與外部類的名字相同。因為在外部引用它時必須給出帶有外部類名的完整名稱(外部類名.內部類名) 3.內部類可以是抽象類或介面,若是介面,則可以由其他巢狀類實現。 4.巢狀類不要濫
Static Nested Class(巢狀類) 和 Inner Class(內部類)的不同
前言:本來是想總結一下inner class 的用法,但是卻發現這幾位頗為親近。索性一起拉出來溜溜。寫作目的:跟 static , final, inner class 搞好關係,以便將來遇見了,就像用if ,else一樣,一清二楚。文中的術語定義以java language spec為準。先想想,要關注的是
Java™ 教程(巢狀類)
巢狀類 Java程式語言允許你在另一個類中定義類,這樣的類稱為巢狀類,如下所示: class OuterClass { ... class NestedClass { ... } } 術語:巢狀類分為兩類:靜態和非靜態,宣告為
Mybatis關聯查詢(巢狀查詢)
三張表:user article blog 表的儲存sql檔案: /* Navicat MySQL Data Transfer Source Server : localhost Source Server Version : 50620 Sourc
在vmware workstation上配置KVM(巢狀虛擬化)
最近想利用vmware workstation做巢狀虛擬化,配置KVM,然後利用Devstack用於搭建Openstack環境, 整套環境在自己的筆記本上構建,重啟筆記本,在BIOS裡開啟了VT-x,然後在vmware workstation上安裝了Ubuntu12.04,
MySQL SQL 多個Join on(表連線) 和Where間的執行順序(nest loop join機制)【轉】
版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/qq_27529917/article/details/78447882 在mysql中,多表連線採用nest loop join,即迴圈巢狀連
oracle 表連線方式: nested loop 巢狀迴圈和Hash Join的比較
一、建立兩張實驗用表:wireless_site.merchant和wireless_site.bb SQL> select count(*) from wireless_site.merchant; COUNT(*) ---------- 14005
圖解Oracle 表連線優化之巢狀迴圈連線(Nested loops join)
當一條SQL語句引用多張表連線時,Oracle的查詢優化器(Optimizer)不僅要確定每張表的訪問路徑,而且需要確定這些表的連線順序和連線方法。查詢優化器的目標是通過儘早地過濾不需要的資料,減少需要處理的資料量。 Oracle的SQL優化器(Optimizer)在執行
oracle: 表連線方式---hash join原理
表的連線方式 是執行計劃生成的重要方面。 各種連線方式代表不同的連線操作演算法。 不同的連線方式也適應不同的資料量和資料分佈情況。 巢狀迴圈,隨即讀成本大,合併排序連線,需要大規模的sort操作,記憶體和temp空間壓力大,在處理海量資料隨機讀,海量排序,都不能被接受。所
MapReduce表連線操作之Reduce端join
一:背景 Reduce端連線比Map端連線更為普遍,因為輸入的資料不需要特定的結構,但是效率比較低,因為所有資料都必須經過Shuffle過程。 二:技術實現 基本思路 (1):Map端讀取所有的檔案,並在輸出的內容里加上標示,代表資料是從哪個檔案裡來的。 (2):在red
ORACLE表空間操作實例
nds 臨時文件 acl efault home const desc 文件大小 extend 本文主要介紹oracle表空間常見的操作實例,包括創建、查詢、增加、刪除、修改。表空間和數據文件常用的數據字典和動態性能視圖包括v$dbfile、v$datafile、d
SQL Server 表的管理_關於表的操作增刪查改的操作的詳解(案例代碼)
har table 詳解 增刪 .com ble tab SQ eat SQL Server 表的管理_關於表的操作增刪查改的操作的詳解(案例代碼) 概述: 表由行和列組成,每個表都必須有個表名。 SQL CREATE TABLE 語法 CREATE T
awk字串操作(字串連結、傳入傳出shell變數) awk 字串連線操作(字串轉數字,數字轉字串) awk當中使用外部變數 awk中使用shell的環境變數 awk如何向shell傳值
1.awk基礎 awk的環境變數及其意義 https://blog.csdn.net/snowpay/article/details/52451718 linux awk命令詳解 https://www.cnblogs.com/xudong-bupt/p/3721210.html 2.aw
MySQL多表連線操作
1 select * from userinfo ,dapartment where userinfo.part_id = dapartment.id; 2 --左連線: 左邊全部顯示 3 select * from userinfo left join dapartment on
Oracle-表的操作
對錶的操作主要分為三種: Oracle的資料型別: 表的重新命名: 表的刪除和回收站 Oracle如果刪除表不會真的刪除表,而是想Windows一樣,進入了回收站,可以恢復和徹底刪除 show recyclebin;//查看回收站 flash
Oracle 表空間和使用者的維護(建立、刪除、修改)
最近為了完成資料在不同庫之間的匯入匯出,臨時建立了不少表空間和使用者,為了保持資料庫的乾淨整潔,根據需要刪除無用的使用者、表空間及物理檔案。 下面是相關的語法操作。 1.查看錶空間 select * from dba_tablespaces 2.查詢物
Oracle 表空間操作記錄
oracl ide 操作 lte res files fault 創建 datadata 1.更改表所屬表空間alter table t_address move tablespace dd_data; 2.查詢表空間所在路徑 select * from dba_data