1. 程式人生 > >Oracle表連線操作——Nest Loop Join(巢狀迴圈)

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