Oracle 訪問路徑

chenoracle發表於2020-03-09

Oracle® Database   SQL Tuning Guide

Part IV   SQL Operators: Access Paths and Joins

---8 Optimizer Access Paths

---9 Joins

8 優化器訪問路徑

8 Optimizer Access Paths

訪問路徑是查詢用於從行源檢索行的一種技術。

8.1 訪問路徑介紹

行源是執行計劃中的一個步驟返回的一組行。行源可以是聯接或分組操作的表、檢視或結果。

一元操作,如訪問路徑,是查詢用來從行源檢索行的一種技術,它接受單個行源作為輸入。例如,全表掃描是檢索單個行源的行。相反,聯接是二進位制的,並且接收來自兩個行源的輸入,資料庫對不同的關係資料結構使用不同的訪問路徑。下表總結了主要資料結構的常用訪問路徑。

優化器考慮不同的可能執行計劃,然後為每個計劃分配成本。優化器選擇成本最低的計劃。通常,對於檢索一小部分錶行的語句,索引訪問路徑更有效,而對於訪問表的大部分時,全表掃描更有效。

8.2 表的訪問路徑

表是Oracle 資料庫中資料組織的基本單位。

關係表是最常見的表型別。關係表具有以下組織特徵:

堆組織的表不會以任何特定的順序儲存行。

索引組織的表根據主鍵值對行進行排序。

外部表是隻讀表,其後設資料儲存在資料庫中,但其資料儲存在資料庫之外。

8.2.1 關於堆組織的表訪問

預設情況下,表 為堆 組織 ,這意味著資料庫將行放在最適合它們的地方,而不是按照使用者指定的順序。

當使用者新增行時,資料庫將這些行放在資料段中第一個可用的空閒空間中。不能保證按插入的順序檢索行。

8.2.1.1 資料塊和段的行儲存 : 初級讀本

資料庫將行儲存在資料塊中。在表中,資料庫可以在塊的底部的任何地方寫入一行。Oracle 資料庫使用塊開銷 ( 包含行目錄和表目錄 ) 來管理塊本身。

一個區段由邏輯上相鄰的資料塊組成。這些塊在磁碟上可能不是物理上連續的。段是一組區段,包含表空間中邏輯儲存結構的所有資料。例如,Oracle 資料庫分配一個或多個區段來形成表的資料段。資料庫還分配一個或多個區段來形成表的索引段。

預設情況下,資料庫使用自動段空間管理(ASSM) 來管理永久的、本地管理的表空間。當會話第一次向表中插入資料時,資料庫將格式化點陣圖塊。點陣圖跟蹤段中的塊。資料庫使用點陣圖查詢空閒塊,然後在寫入每個塊之前對其進行格式化。 ASSM 在塊之間展開插入,以避免併發問題。

高水位標誌(HWM) 是資料塊未格式化且從未使用過的段中的點。在 HWM 下面,一個塊可以格式化和寫入,格式化和空,或未格式化。低高水位標誌 ( HWM) 標誌所有塊已知被格式化的點,因為它們要麼包含資料,要麼以前包含資料。

在全表掃描期間,資料庫將所有塊讀取到低HWM ,這是已知要格式化的,然後讀取段點陣圖,以確定 HWM 和低 HWM 之間的哪些塊格式化了,可以安全讀取。資料庫知道不能讀過 HWM ,因為這些塊是非格式化的。

8.2.1.2  row id 對行訪問的重要性

堆組織的表中的每一行都有一個rowid 惟一對應於行塊的實體地址。 rowid 是一行的 10 位元組實體地址。

rowid 指向特定的檔案、塊和行號。例如,在 rowid AAAPecAAFAAAABSAAA 中,最後的 AAA 表示行號。行號是行目錄項的索引。行目錄項包含指向塊上該行位置的指標。

資料庫有時可以在塊的底部移動一行。例如,如果啟用了行移動,那麼由於分割槽鍵更新、閃回表操作、收縮表操作等原因,行可以移動。如果資料庫在一個塊中移動一行,那麼資料庫將更新目錄條目來修改指標。rowid 保持不變。

Oracle 資料庫在內部使用 rowids 構建索引。例如, B-tree 索引中的每個鍵都與一個 rowid 相關聯,該 rowid 指向相關行的地址。物理行 id 提供對錶行最快的可能訪問,使資料庫能夠以最少的 I/O 檢索行。

8.2.1.3   直接 路徑讀取 ( Direct Path Reads )

在直接路徑讀取中,資料庫直接將緩衝區從磁碟讀取到PGA ,完全繞過 SGA

下圖顯示了在SGA 中儲存緩衝區的分散讀取和順序讀取與直接路徑讀取之間的區別。

Oracle 資料庫可能執行直接路徑讀取的情況包括 :

執行 CREATE TABLE AS SELECT 語句

執行 ALTER REBUILD ALTER MOVE 語句

從臨時表空間讀取資料

並行查詢

讀取 LOB

8.2.2   表掃描 (Full Table Scan)

全表掃描從表中讀取所有行,然後過濾掉不符合選擇條件的行。

8.2.2.1 優化器何時 考慮全表掃描

通常,優化器在不能使用不同的訪問路徑或另一個可用的訪問路徑成本更高時,會選擇全表掃描。

下表顯示了選擇全表掃描的典型原因。

原因:沒有索引

如果不存在索引,那麼優化器將使用全表掃描。

原因:查詢謂詞對索引列應用一個函式。

除非索引是基於函式的索引,否則資料庫將索引該列的值,而不是應用該函式的列的值。典型的應用程式級錯誤是索引一個字元列( char_col) ,然後使用語法 ( WHERE char_col=1) 查詢該列。資料庫隱式地將 TO_NUMBER 函式應用於常數 1 ,這阻止了索引的使用。

原因:一個SELECT COUNT (*) 發出查詢,並且存在索引,但是索引的列包含空值。

優化器不能使用索引來計算錶行數,因為索引不能包含空條目。

原因: 查詢謂詞不使用B-tree 索引 前導列

例如,一個索引可能存在於employees (first_name,last_nam e) 列。 如果一個使用者發出一個查詢,其中last_name='KING' 的謂詞,那麼優化器可能不會選擇一個索引,因為列 first_name 不在謂詞中。但是,在這種情況下,優化器 可能選擇使用索引 跳躍 掃描。

原因:查詢選擇性很差

如果優化器確定查詢需要表中的大多數塊,那麼它將使用全表掃描,即使有可用的索引。全表掃描可以使用較大的I/O 呼叫。進行更少的大型 I/O 呼叫比進行許多小型呼叫 成本更低

原因:表統計資訊過時了

例如,一個表曾經很小,但是現在變大了。如果表統計資訊已經過時,並且沒有反映表的當前大小,那麼優化器不知道 現在走 索引 掃描 比全表掃描更 高效

原因:表很小

如果一個表在高水位線下包含少於n 個塊,其中 n 等於 DB_FILE_MULTIBLOCK_READ_COUNT 的設定初始化引數,則全表掃描可能比索引範圍掃描 成本更低 。不管被訪問的表或索引有多少,掃描的成本都可能較低。

原因:表具有高度的並行性。

表的高度並行性使優化器傾向於全表掃描而不是範圍掃描。查詢ALL_TABLES 中的值。度列確定並行度。

原因:該查詢使用一個全表表掃描hint

提示FULL( 表別名 ) 指示優化器使用全表掃描。

例如:select  /*+ full(t1) */ * from t1;

8.2.2.2 全表掃描的工作原理

在全表掃描中,資料庫順序讀取高水位標記下的每個格式化塊。資料庫只讀取每個塊一次。

下面的圖形描述了對錶段的掃描,顯示了掃描如何跳過高水位標記下的未格式化塊。

由於這些塊是相鄰的,因此資料庫可以通過使I/O 呼叫大於單個塊 ( 稱為多塊讀 ) 來加快掃描速度。 呼叫的大小範圍從一個塊到DB_FILE_MULTIBLOCK_READ_COUNT 初始化引數指定的塊的數量。例如,將此引數設定為 4 指示資料庫在單個呼叫中讀取最多 4 個塊。

在全表掃描期間快取塊的演算法非常複雜。例如,資料庫根據表的大小以不同的方式快取塊。

8.2.2.3 全表掃描 : 示例

這個示例掃描hr.employees 表。

以下是關於月薪超過$4000 查詢 :

SELECT salary FROM hr.employees WHERE salary > 4000;

8-1 全表掃描

使用DBMS_XPLAN.DISPLAY_CURSOR 函式 檢視執行計劃 。由於salary 列上不存在索引,優化器無法使用索引範圍掃描,因此使用 表掃描。

8.2.3   通過 Rowid 訪問表 (Table Access by Rowid)

rowid 是資料儲存位置的內部表示。

row rowid 指定資料檔案和資料塊,其中包含該行和該行在該塊中的位置。通過指定一行的 rowid 來定位該行是檢索單個行最快的方法,因為它指定了該行在資料庫中的確切位置。

注意:

Rowids 可以在不同的版本之間進行更改。不建議基於位置訪問資料,因為行可以移動。

8.2.3.1   優化器通過Rowid 選擇表訪問

在大多數情況下,資料庫在掃描一個或多個索引之後通過rowid 訪問表。

但是,rowid 對錶的訪問不需要每次掃描索引。如果索引包含所有需要的列,則 rowid 訪問可能不會發生。

8.2.3.2 Rowid 的表訪問 工作原理

要通過rowid 訪問表,資料庫執行多個步驟。資料庫的工作如下 :

1. 從語句 WHERE 子句或通過一個或多個索引的索引掃描獲取所選行的 rowid, 對於不在索引中出現的語句中的列,可能需要訪問

2. 根據表中的 rowid 定位每個選定的行

8.2.3.3 Rowid 訪問表 : 示例

這個例子演示了hr.employees 表的rowid 訪問 。假設您執行以下查詢:

SELECT * FROM employees WHERE employee_id > 190;

以下計劃的第2 步顯示 hr.EMPLOYES 表上 emp_emp_id_pk 索引的範圍掃描。資料庫使用從索引獲得的 rowid employees 表中查詢相應的行,然後檢索它們。步驟 1 中顯示的批處理訪問意味著資料庫從索引中檢索一些 rowid ,然後嘗試按塊訪問行,以改進群集並減少資料庫必須訪問塊的次數。

8.2.4   樣本表掃描 (Sample Table Scans)

樣本表 掃描從簡單表或複雜的SELECT 語句 ( 例如涉及連線和檢視的語句 ) 中檢索隨機資料樣本。

8.2.4.1 優化器 何時考慮 選擇樣本表掃描

當語句FROM 子句包含 sample 關鍵字時,資料庫使用示例表掃描。

本條格式如下:

樣本(樣本百分比)

資料庫讀取表中指定百分比的行以執行示例表掃描。

樣本塊(樣本百分比)

資料庫讀取指定百分比的表塊以執行示例表掃描。

sample_percent 指定要包含在樣本中的總行或塊計數的百分比。該值必須在 .000001 100 (但不包括 100 )之間。

此百分比表示為樣本選擇的每一行或塊取樣中的每一行簇的概率。這並不意味著資料庫會準確地檢索行的樣本百分比。

注:

只有在全表掃描或索引快速全掃描期間才可以進行塊取樣。如果存在更有效的執行路徑,則資料庫不取樣塊。要確保對特定表或索引進行塊取樣,請使用FULL index_FFS 提示。

8.2.4.2 樣本表掃描:示例

此示例使用示例表掃描訪問1% employees 表,按塊而不是行進行取樣。

示例8-2   示例表掃描

SELECT * FROM hr.employees SAMPLE BLOCK (1);

此語句的解釋計劃輸出可能如下所示:

8.2.5  In-Memory 表掃描 (In-Memory Table Scans)

In-Memory 表掃描 從記憶體列儲存(IM 列儲存)中檢索行。

IM 列儲存 是一個可選的SGA 區域,它以一種特殊的列格式儲存表和分割槽的副本,這種格式是為快速掃描而優化的。

8.2.5.1 優化器選擇記憶體表掃描時

優化器成本模型知道IM 列儲存的內容。

當使用者執行引用IM 列儲存中的表的查詢時,優化器計算所有可能的訪問方法(包括記憶體表掃描)的成本,並選擇成本最低的訪問方法。

8.2.5.2In-Memory 查詢控制元件

可以使用初始化引數控制 In-Memory 查詢。

以下資料庫初始化引數會影響 In-Memory 的特性:

•INMEMORY_QUERY

此引數在會話級或系統級啟用或禁用資料庫的 In-Memory 查詢。當您希望測試帶有或不帶有IM 列儲存的工作負載時,此引數非常有用。

•OPTIMIZER_INMEMORY_AWARE

該引數啟用(TRUE) 或禁用 (FALSE) 優化器成本模型、表擴充套件、 bloom 過濾器等的所有In-Memory 增強。將引數設定為FALSE 會導致優化器在優化 SQL 語句時忽略 表的In-Memory 屬性。

•OPTIMIZER_FEATURES_ENABLE

當設定為小於12.1.0.2 的值時,此引數的效果與將 OPTIMIZER_INMEMORY_AWARE 設定為 FALSE 相同。

要啟用或禁用In-Memory 查詢,您可以指定 INMEM ORY NO_INMEMORY 提示,它們相當於每個查詢的 INMEMORY_QUERY 初始化引數。如果 SQL 語句使用 INMEMORY 提示,但是它引用的物件還沒有載入到 IM 列儲存中,那麼資料庫在執行語句之前不會等待物件被填充到 IM 列儲存中。

但是,物件的初始訪問將觸發記憶體列儲存中的物件填充。

8.2.5.3 記憶體表掃描 In-Memory Table Scans: 示例

這個示例顯示了一個執行計劃,其中包括In-Memory Table Scans 操作。

Example 8-3 In-Memory Table Scan

SELECT *

FROM oe.product_information WHERE list_price > 10

ORDER BY product_id

該語句的計劃如下所示,第2 步中的 INMEMORY 關鍵字表示從 IM 列儲存中訪問了部分或全部物件 :

8.3 B-Tree 索引訪問路徑

索引是一個可選的結構,與表或 聚簇表 相關聯,有時可以加快資料訪問速度。

通過在表的一個或多個列上建立索引,您可以在某些情況下從表中檢索隨機分佈的一小組行。索引是減少磁碟I/O 的許多方法之一。

8.3.1   關於 B-Tree 索引訪問

b -tree( 平衡樹的縮寫 ) 是最常見的資料庫索引型別。

B- tree 索引是按範圍劃分的值的有序列表。通過將鍵與行或行範圍相關聯, B-Tree 為廣泛的查詢( 包括精確匹配和範圍搜尋 ) 提供了出色的檢索效能。

8.3.1.1   B-Tree 索引結構

B-tree 索引有兩種型別的塊 : 用於搜尋的分支塊和儲存值的葉塊。

下圖說明了 B-Tree 索引的邏輯結構。分支塊儲存在兩個鍵之間進行分支決策所需的最小鍵字首。葉塊包含每個索引資料值和用於定位實際行的相應rowid 。每個索引條目按 ( 鍵, rowid) 排序。葉塊是雙向連線的。

8.3.1.2 索引儲存如何影響索引掃描

點陣圖索引塊可以出現在索引段的任何地方。

8-3 顯示了相鄰的葉塊。例如, 1-10 塊在 11-19 塊的旁邊和前面。這個排序說明了連線索引項的連結串列。但是,索引塊不需要按順序儲存在索引段中。例如, 246-250 塊可以出現在段中的任何位置,包括 1-10 塊的前面。因此,有序的索引掃描必須執行單塊 I/O 。資料庫必須讀取一個索引塊,以確定接下來必須讀取哪個索引塊。

索引塊體將索引項儲存在堆中,就像錶行一樣。例如,如果值10 首先插入到一個表中,那麼帶有鍵 10 的索引條目可能會插入到索引塊的底部。如果 0 是下一個插入到表中的,那麼鍵 0 的索引條目可能會被插入到條目的頂部,其長度為 10 。因此,塊體中的索引項不是按鍵順序儲存的。但是,在索引塊中,行標頭按鍵順序儲存記錄。例如,標頭中的第一條記錄用鍵 0 指向索引條目,以此類推,直到用鍵 10 指向索引條目的記錄為止。因此,索引掃描可以讀取行標頭來確定從何處開始和結束範圍掃描,從而避免了讀取塊中的每個條目。

8.3.1.3 唯一和非唯一索引

在非惟一索引中,資料庫通過將rowid 作為額外的列附加到鍵上來儲存它。該條目新增一個長度位元組以使鍵唯一。

例如,圖8-3 所示的非唯一索引中的第一個索引鍵是對 0,rowid ,而不是簡單的 0 。資料庫按索引鍵值排序,然後按 rowid 升序排序。例如,條目的排序如下 :

0,AAAPvCAAFAAAAFaAAa

0,AAAPvCAAFAAAAFaAAg

0,AAAPvCAAFAAAAFaAAl

2,AAAPvCAAFAAAAFaAAm

在唯一索引中,索引鍵不包括rowid 。資料庫僅根據索引鍵值( 0 1 2 ) 對資料進行排序。

8.3.1.4   B-Tree 索引和 Null

B-tree 索引從不儲存完全 空值 ,這對於優化器如何選擇訪問路徑非常重要。這個規則的結果是單列B -Tree 索引從不儲存空值。

一個例子有助於說明。hr.employees 表在 employee_id 上有一個主鍵索引,在 department_id 上有一個唯一的索引。 department_id 列可以包含空值,使其成為可空列,但 employee_id 列不能。

SQL> SELECT COUNT(*) FROM employees WHERE department_id IS NULL;

 COUNT(*)

----------

 1

SQL> SELECT COUNT(*) FROM employees WHERE employee_id IS NULL;

 COUNT(*)

----------

 0

下面的示例顯示優化器為hr.employees 中所有部門 id 的查詢選擇了一個 表掃描。優化器無法對employees.department_id 使用索引,因為索引不能保證包含表中每一行的條目。

下面的示例顯示優化器可以使用department_id 上的索引查詢特定的 department id ,因為所有非空行都被索引。

以下示例顯示,當謂詞排除空值時,優化器選擇索引掃描:

8.3.2   索引唯一掃描 (Index Unique Scans)

索引唯一掃描最多返回1 行資料

8.3.2.1 優化器 何時 考慮索引唯一掃描

索引唯一掃描需要相等謂詞。

具體來說,只有當查詢謂詞使用相等運算子引用唯一索引鍵中的所有列時,資料庫才會執行唯一掃描,例如prod_id=10

唯一或主鍵約束本身不足以生成索引唯一掃描,因為列上可能已存在非唯一索引。考慮以下示例,該示例建立t_ table ,然後在numcol 上建立非唯一索引:

SQL> CREATE TABLE t_table(numcol INT);

SQL> CREATE INDEX t_table_idx ON t_table(numcol);

SQL> SELECT UNIQUENESS FROM USER_INDEXES WHERE INDEX_NAME = 'T_TABLE_IDX';

UNIQUENES

---------

NONUNIQUE

以下程式碼在具有非唯一索引的列上建立主鍵約束,從而導致索引範圍掃描而不是索引唯一掃描:

SQL> ALTER TABLE t_table ADD CONSTRAINT t_table_pk PRIMARY KEY(numcol);

SQL> SET AUTOTRACE TRACEONLY EXPLAIN

SQL> SELECT * FROM t_table WHERE numcol = 1;

可以使用INDEX alias INDEX_name )提示指定要使用的索引,但不能指定特定型別的索引訪問路徑。

8.3.2.2 索引唯一掃描的工作原理

掃描將按順序搜尋索引以查詢指定的鍵。索引唯一掃描在找到第一條記錄後立即停止處理,因為不可能有第二條記錄。資料庫從索引項獲取rowid ,然後檢索 rowid 指定的行。

下圖說明了索引唯一掃描。語句請求prod_ID 列中產品 ID 19 的記錄,該列具有主鍵索引。

8.3.2.3 索引唯一掃描:示例

此示例使用唯一掃描從products 表檢索行。

以下語句查詢sh.products 表中產品 19 的記錄:

SELECT * FROM sh.products WHERE prod_id = 19;

由於products.prod_id 列上存在主鍵索引,並且 WHERE 子句使用相等運算子引用所有列,優化器選擇唯一掃描:

8.3.3   索引 範圍掃描 (Index Range Scans)

索引範圍掃描是值的有序掃描。

掃描中的範圍可以在兩邊都有界,也可以在一邊或兩邊都無界。優化器通常為具有高選擇性的查詢選擇範圍掃描。

預設情況下,資料庫按升序儲存索引,並以相同的順序掃描索引。例如,使用謂詞department_id >= 20 的查詢使用範圍掃描來返回按索引鍵 20 30 40 等排序的行。如果多個索引項具有相同的鍵,那麼資料庫將按 rowid 升序返回它們,因此 0 AAAPvCAAFAAAAFaAAa 後面緊跟著 0 AAAPvCAAFAAAAFaAAg ,以此類推。

索引範圍降序掃描與索引範圍降序掃描相同,不同之處在於資料庫按降序返回行。通常,在按降序排列資料時,或者在查詢小於指定值的值時,資料庫使用降序掃描。

8.3.3.1 優化器 何時 考慮索引範圍掃描

對於索引範圍掃描,索引鍵必須可能有多個值。具體來說,優化器考慮索引範圍掃描在以下情況:

在條件中指定一個索引的一個或多個前導列。

條件指定一個或多個表示式和邏輯( 布林 ) 操作符的組合,並返回 TRUE FALSE UNKNOWN 值。條件的例子包括 :

– department_id = :id

– department_id < :id

– department_id > :id

和前面的條件的組合,如 department_id >:low department_id <:hi

注意:

為了讓優化器考慮範圍掃描,像'%ASD' 這樣的形式 col1 的萬用字元搜尋不能位於前導位置。

索引鍵可以有 0 1 或更多的值。

提示:

如果需要排序的資料,請使用ORDER   BY 子句,不要依賴索引。如果索引可以滿足 ORDERBY 子句,那麼優化器將使用此選項,從而避免排序。

當索引可以滿足ORDER BY descending 子句時,優化器會考慮索引範圍掃描遞減。

如果優化器選擇完整表掃描或其他索引,則可能需要提示來強制此訪問路徑。INDEX tbl_alias ix_name )和 INDEX_DESC tbl_alias ix_name )提示指示優化器使用特定索引。

8.3.3.2 索引範圍掃描的工作原理

在索引範圍掃描期間,Oracle 資料庫從根目錄轉到分支目錄。一般來說,掃描演算法如下:

1. 讀取根塊。

2. 讀取分支塊。

3. 交替執行以下步驟,直到檢索到所有資料:

a 、 讀取葉塊以獲取 rowid

b 、 讀取表塊以檢索行。

注:

在某些情況下,索引掃描讀取一組索引塊,對行ID 進行排序,然後讀取一組表塊。

因此,為了掃描索引,資料庫在葉塊中向後或向前移動。例如,對介於20 40 之間的 IDs 的掃描定位具有 20 或更大的最小鍵值的第一個葉塊。掃描在葉節點的連結列表中水平進行,直到找到大於 40 的值,然後停止。

下圖說明了使用升序的索引範圍掃描。語句請求department_id 列中值為 20 的員工記錄,該列具有非唯一索引。在本例中,存在部門 20 2 個索引項。

8.3.3.3 索引範圍掃描:示例

此示例使用索引範圍掃描從employees 表檢索一組值。

以下語句查詢部門20 中薪資大於 1000 的員工的記錄:

SELECT *

FROM employees

WHERE department_id = 20 AND salary > 1000;

前面的查詢基數較低(返回幾行),因此該查詢使用department _ id 列上的索引。資料庫掃描索引,從 employees 表中獲取記錄,然後對這些獲取的記錄應用 salary>1000 篩選器以生成結果。

8.3.3.4 索引範圍掃描 降序 :示例

本例使用索引按排序順序從employees 表中檢索行。

以下語句按降序查詢部門20 中員工的記錄:

SELECT *

FROM employees

WHERE department_id < 20 ORDER BY department_id DESC;

前面的查詢基數較低,因此查詢使用department_id 列上的索引

資料庫將定位第一個索引葉塊,該葉塊包含的最大鍵值不超過20 。然後,掃描通過葉節點的連結列表水平向左進行。資料庫從每個索引項獲取 rowid ,然後檢索 rowid 指定的行。

8.3.4 索引全掃描 (Index Full Scans)

索引完全掃描按順序讀取整個索引。索引完全掃描可以消除單獨的排序操作,因為索引中的資料是按索引鍵排序的。

8.3.4.1 優化器 何時 考慮索引全掃描

優化器在各種情況下考慮索引完全掃描。這些情況包括:

謂詞引用索引中的列。此列不必是前導列。

未指定謂詞,但滿足以下所有條件:

表和查詢中的所有列都在索引中。

至少有一個索引列不為空。

查詢包括索引的不可為空列上的 ORDER BY 操作

8.3.4.2 索引完整掃描的工作原理

資料庫讀取根塊,然後向下導航索引的左側(如果執行降序全掃描,則向右導航),直到到達葉塊。

然後資料庫到達一個葉塊,掃描在索引的底部進行,一次一個塊,按排序順序進行。資料庫使用單塊I/O ,而不是多塊 I/O

下圖顯示了索引完全掃描。一個語句請求按部門id 排序 查詢 部門記錄。

8.3.4.3 索引全掃描:示例

本例使用索引完全掃描來滿足帶有ORDERBY 子句的查詢。

以下語句按部門ID 的順序查詢部門的 ID 和名稱:

SELECT department_id, department_name FROM   departments

ORDER BY department_id;

資料庫定位第一個索引葉塊,然後通過葉節點的連結列表水平向右移動。對於每個索引項,資料庫從該項獲取rowid ,然後檢索由 rowid 指定的錶行。

因為索引是按部門id 排序的,所以資料庫避免了對檢索到的行進行排序的單獨操作。

8.3.5 索引快速全掃描 (Index Fast Full Scans)

索引幾乎完全掃描按未排序的順序讀取索引塊,因為它們存在於磁碟上。此掃描不使用索引來探測表,而是讀取索引而不是表,實質上是將索引本身用作表。

8.3.5.1 優化器 何時 考慮索引快速全掃描

當查詢只訪問索引中的屬性時,優化器會考慮此掃描。

注:

與完全掃描不同,快速完全掃描無法消除排序操作,因為它沒有按順序讀取索引。

INDEX_FFS table_name INDEX_name )提示強制執行快速完整索引掃描。

8.3.5.2 索引快速全掃描的工作原理

資料庫使用多塊I/O 讀取根塊以及所有葉塊和分支塊。資料庫忽略分支和根塊,並讀取葉塊上的索引項。

8.3.5.3 索引快速全掃描:示例

此示例使用快速的完整索引掃描作為優化器提示的結果。

以下語句按部門ID 的順序查詢部門的 ID 和名稱:

SELECT /*+ INDEX_FFS(departments dept_id_pk) */ COUNT(*) FROM departments;

以下計劃顯示優化器選擇了快速 索引掃描:

8.3.6 索引 跳躍 掃描 (Index Skip Scans)

當組合索引的初始列被跳過 或未在查詢中指定時,將發生索引跳過掃描。

8.3.6.1   優化器 何時 考慮 跳躍 索引掃描

通常,跳過掃描索引塊比掃描表塊快,也比執行全索引掃描快。

當滿足以下條件時,優化器將考慮跳過掃描:

在查詢謂詞中沒有指定複合索引的前導列。

例如,查詢謂詞不引用cust_gender 列,而複合索引鍵是 (cust_gender,cust_email)

複合索引的前導列中 選擇性特別差 ,但是索引的非前導鍵 選擇性特別高

例如,如果複合索引鍵是(cust_gender,cust_email) ,那麼 cust_gender 列只有兩個不同的值,而 cust_email 有數千個。

8.3.6.2   索引 跳躍 掃描的工作原理

索引 跳躍 掃描在邏輯上將複合索引拆分為更小的子索引。

索引前導列中不同值的數目決定邏輯子索引的數目。數目越少,優化器必須建立的邏輯子索引就越少,掃描的效率就越高。掃描會分別讀取每個邏輯索引,並跳過 非前導列上不符合篩選條件的索引塊。

8.3.6.3   索引 跳躍 掃描:示例

本例使用索引 跳躍 掃描來滿足sh.customers 表的查詢。

customers 表包含一列 cust_gender ,其值為 M F 。以使用者 sh 的身份登入資料庫時,可以在列( cust_gender cust_email )上建立複合索引,如下所示:

CREATE INDEX cust_gender_email_ix

ON sh.customers (cust_gender, cust_email);

從概念上講,索引的一部分可能如下所示,其中F M 的性別值是索引的 前導列

F,Wolf@company.example.com,rowid

F,Wolsey@company.example.com,rowid

F,Wood@company.example.com,rowid

F,Woodman@company.example.com,rowid

F,Yang@company.example.com,rowid

F,Zimmerman@company.example.com,rowid

M,Abbassi@company.example.com,rowid

M,Abbey@company.example.com,rowid

sh.customers 表中對客戶執行以下查詢:

SELECT *

FROM sh.customers

WHERE cust_email = 'Abbey@company.example.com';

資料庫可以使用客戶性別電子郵件索引的跳過掃描,即使在WHERE 子句中未指定 cust 性別。在示例索引中,前導列 cust_gender 有兩個可能的值: F M 。資料庫在邏輯上將索引拆分為兩個。一個子索引具有鍵 F ,其項的格式如下:

F,Wolf@company.example.com,rowid

F,Wolsey@company.example.com,rowid

F,Wood@company.example.com,rowid

F,Woodman@company.example.com,rowid

F,Yang@company.example.com,rowid

F,Zimmerman@company.example.com,rowid

第二個子索引具有鍵M ,其條目的格式如下:

M,Abbassi@company.example.com,rowid

M,Abbey@company.example.com,rowid

在搜尋電子 郵箱為 Abbey@company.example.com 的客戶記錄時,資料庫首先搜尋前導值為 F 的子索引,然後搜尋前導值為 M 的子索引。概念上,資料庫按如下方式處理查詢:

執行計劃如下:

8.3.7 索引連線掃描 (Index Join Scans)

索引聯接掃描是多個索引的雜湊聯接,這些索引一起返回查詢請求的所有列。資料庫不需要訪問表,因為所有資料都是從索引中檢索的。

8.3.7.1 優化器 何時 考慮索引連線掃描

在某些情況下,避免表訪問是最經濟高效的選擇。優化器在以下情況下考慮索引聯接:

多個索引的雜湊連線檢索查詢請求的所有資料,而不需要表訪問。

從表中檢索行的成本高於不從表中檢索行而讀取索引的成本。索引連線通常很昂貴。

例如,當掃描兩個索引並將它們連線起來時,選擇最具選擇性的索引,然後探測表通常成本較低。

您可以使用index_join table_name )提示指定索引聯接。

8.3.7.2 索引連線掃描的工作 原理

索引聯接涉及掃描多個索引,然後對從這些掃描中獲得的 row id 使用雜湊聯接返回行。

在索引連線掃描中,總是避免表訪問。例如,在一個表上連線兩個索引的過程如下:

1. 掃描第一個索引以檢索 rowid

2. 掃描第二個索引以檢索 rowid

3. rowid 執行雜湊聯接以獲取行。

8.3.7.3 索引連線掃描:示例

此示例查詢姓氏以A 開頭並指定索引聯接的員工的姓氏和電子郵件。

SELECT /*+ INDEX_JOIN(employees) */ last_name, email FROM employees

WHERE last_name like 'A%';

在(姓氏、名字)和電子郵件列上存在單獨的索引。emp_name_ix 索引的一部分可能如下所示:

Banda,Amit,AAAVgdAALAAAABSABD

Bates,Elizabeth,AAAVgdAALAAAABSABI

Bell,Sarah,AAAVgdAALAAAABSABc

Bernstein,David,AAAVgdAALAAAABSAAz

Bissot,Laura,AAAVgdAALAAAABSAAd

Bloom,Harrison,AAAVgdAALAAAABSABF

Bull,Alexis,AAAVgdAALAAAABSABV

emp_email_uk 索引的第一部分可能如下所示:

ABANDA,AAAVgdAALAAAABSABD

ABULL,AAAVgdAALAAAABSABV

ACABRIO,AAAVgdAALAAAABSABX

AERRAZUR,AAAVgdAALAAAABSAAv

AFRIPP,AAAVgdAALAAAABSAAV

AHUNOLD,AAAVgdAALAAAABSAAD

AHUTTON,AAAVgdAALAAAABSABL

以下示例使用DBMS_XPLAN.DISPLAY_CURSOR 函式檢索計劃。資料庫檢索 emp_email_uk 索引中的所有 rowid ,然後檢索 emp_name_ix 中以 A 開頭的姓氏的 rowid 。資料庫使用雜湊聯接來搜尋兩組 rowid 中的匹配項。例如, rowid aaavgdalaaaabsabd 同時出現在兩組 rowid 中,因此資料庫會在 employees 表中探測與此 rowid 對應的記錄。

8.4 點陣圖索引訪問路徑

Bitmap Index Access Paths

點陣圖索引將索引的資料與rowid 範圍相結合。

8.4.1 關於點陣圖索引訪問

在傳統的B -Tree 索引中,一個索引入口指向一行。在點陣圖索引中,鍵是索引資料和rowid 範圍的組合。

資料庫為每個索引鍵儲存至少一個點陣圖。點陣圖中的每個值(由1 0 個值組成)都指向 rowid 範圍內的一行。因此,在點陣圖索引中,一個索引條目指向一組行,而不是一行。

8.4.1.1 點陣圖索引和 B 樹索引之間的差異

點陣圖索引使用與B 樹索引不同的鍵,但儲存在 B 樹結構中。

下表顯示了索引項型別之間的差異。

資料庫將點陣圖索引儲存在B 樹結構中。資料庫可以在鍵的第一部分(即定義索引的屬性集)上快速搜尋 B 樹,然後獲得相應的 rowid 範圍和點陣圖。

8.4.1.2 點陣圖索引的用途

點陣圖索引通常適用於具有少量或中度不同值(NDV )的不經常修改的資料。

一般來說,B- 樹索引適用於 NDV 高、 DML 活動頻繁的列。例如,優化器可以為 sales.amount 列的查詢選擇一個 B 樹索引,該列返回很少的行。相比之下, customers.state customers.county 列是點陣圖索引的候選列,因為它們很少有不同的值,很少更新,並且可以從高效的 and OR 操作中獲益。

點陣圖索引是在資料倉儲中加速特殊查詢的有用方法。它們是 星型轉換 的基礎。具體來說,點陣圖索引在包含以下內容的查詢中非常有用:

在訪問表本身之前, WHERE 子句中有多個條件,資料庫會篩選出滿足某些條件(而不是全部條件)的行。

AND OR NOT 在具有低或中等NDV 列上操作

組合點陣圖索引使這些操作更有效。資料庫可以很快地從點陣圖索引中合併點陣圖。例如,如果customers.state customers.county 列上存在點陣圖索引,則這些索引可以極大地提高以下查詢的效能:

SELECT *

FROM customers WHERE state = 'CA'

AND county = 'San Mateo'

資料庫可以有效地將合併點陣圖中的1 個值轉換為 rowids

計數功能

資料庫可以掃描點陣圖索引,而無需掃描表。

選擇空值的謂詞

B 樹索引不同,點陣圖索引可以包含空值。對列中的空值進行計數的查詢可以使用點陣圖索引,而無需掃描表。

 

低頻率的 DM L 操作

原因是一個索引鍵指向許多行。如果會話修改了索引資料,那麼資料庫就不能鎖定點陣圖中的一個位:相反,資料庫會鎖定整個索引項,這實際上會鎖定點陣圖指向的行。例如,如果特定客戶的居住縣從San Mateo 更改為 Alameda ,則資料庫必須獨佔訪問點陣圖中的 San Mateo 索引項和 Alameda 索引項。在提交之前,不能修改包含這兩個值的行。

8.4.1.3 點陣圖和 rowids

對於點陣圖中的特定值,如果行值與點陣圖條件匹配,則該值為1 ;如果不匹配,則該值為 0 。基於這些值,資料庫使用內部演算法將點陣圖對映到 rowid

點陣圖項包含索引值、rowid 範圍(起始行和結束行 id )和點陣圖。點陣圖中的每個 0 1 值都是 rowid 範圍的偏移量,並對映到表中的潛在行,即使該行不存在。因為塊中可能的行數是預先確定的,所以資料庫可以使用範圍端點來確定範圍中任意行的 row id

注:

Hakan 因子是點陣圖索引演算法用於限制 Oracle 資料庫假定可以儲存在單個塊中的行數的優化。通過人為地限制行數,資料庫減小了點陣圖的大小。

8-4 顯示了 sh.customers.cust_martin_status 列的部分示例點陣圖,該點陣圖可以為空。實際索引有 12 個不同的值。示例中僅顯示 3 個:空、已婚和單身。

如表8-4 所示,點陣圖索引可以包含完全由空值組成的鍵,這與 B 樹索引不同。在表 8-4 中,範圍內第 6 行的空值為 1 ,這意味著範圍內第 6 行的客戶婚姻狀況值為空。索引空值對於某些 SQL 語句(例如具有聚合函式計數的查詢)非常有用。

8.4.1.4 點陣圖連線索引 (Bitmap Join Indexes)

點陣圖連線索引是用於連線兩個或多個表的點陣圖索引。

優化器可以使用點陣圖連線索引來減少或消除計劃執行期間必須連線的資料量。點陣圖連線索引在儲存方面比物化連線檢視更有效。

以下示例在sh.sales sh.customers 表上建立點陣圖索引:

CREATE BITMAP INDEX cust_sales_bji ON sales(c.cust_city) FROM sales s, customers c

WHERE c.cust_id = s.cust_id LOCAL;

前面CREATE 語句中的 FROM WHERE 子句表示表之間的聯接條件。 customers.cust_city 列是索引鍵。

索引中的每個鍵值表示customers 表中可能的城市。從概念上講,索引的鍵值可能如下所示,每個鍵值關聯一個點陣圖:

點陣圖中的每個位對應於sales 表中的一行。在 Smithville 鍵中,值 1 表示 sales 表中的第一行對應於銷售給 Smithville 客戶的產品,而值 0 表示第二行對應於未銷售給 Smithville 客戶的產品。

考慮以下對史密斯維爾客戶的單獨銷售數量的查詢:

SELECT COUNT (*)

FROM sales s, customers c WHERE c.cust_id = s.cust_id

AND c.cust_city = 'Smithville';

下面的計劃顯示,資料庫讀取Smithville 點陣圖來獲得 Smithville sales 的數量 ( 步驟 4) ,從而避免了 customer sales 表的連線。

8.4.1.5 點陣圖儲存 (Bitmap Storage)

點陣圖索引位於B -Tree 結構中,使用分支塊和葉塊,就像在B -Tree 中一樣。

例如,如果customers.cust_martin_status 列有 12 個不同的值,則一個分支塊可能指向 keys married rowid range single rowid range ,另一個分支塊可能指向 widowed rowid range 鍵,依此類推。或者,單個分支塊可以指向包含所有 12 個不同鍵的葉塊。

每個索引列值可以有一個或多個點陣圖塊,每個點陣圖塊都有自己的rowid 範圍,在一個或多個區段中佔據一組連續的行。資料庫可以使用點陣圖塊來分解相對於塊大小較大的索引項。例如,資料庫可以將一個索引項分成三個部分,前兩個部分位於同一區段的單獨塊中,最後一個部分位於不同區段的單獨塊中。

為了節省空間,Oracle 資料庫可以壓縮 0 個值的連續範圍。

8.4.2 點陣圖轉換為 Rowid (Bitmap Conversion to Rowid)

點陣圖轉換在點陣圖中的條目和表中的行之間進行轉換。轉換可以從條目轉到行(到ROWID ),也可以從行轉到條目(從 ROWID )。

8.4.2.1 優化器 何時考慮 選擇將點陣圖轉換為Rowid

每當優化器使用點陣圖索引項從表中檢索一行時,都會使用轉換。

8.4.2.2 如何將點陣圖轉換為 Rowid

從概念上講,點陣圖可以表示為表。

例如,表8-4 將點陣圖表示為一個表,其中客戶行號作為列, cust_marital_status 值作為行。表 8-4 中的每個欄位的值都是 1 0 ,表示一行中的一個列值。從概念上講,點陣圖轉換使用一個內部演算法,該演算法表示 點陣圖中的 F 欄位對應於表中第 m 個塊的第 n ,或者 表中第 m 個塊的第 n 行對應於點陣圖中的 F 欄位

8.4.2.3 點陣圖 轉換 Rowid: 示例

在本例中,優化器選擇點陣圖轉換操作來滿足使用範圍謂詞的查詢。

sh.customers 表的查詢選擇 1918 年以前出生的所有客戶的姓名 :

SELECT cust_last_name, cust_first_name FROM customers

WHERE cust_year_of_birth < 1918;

下面的計劃顯示,資料庫使用範圍掃描查詢所有小於1918 的鍵值 ( 步驟 3) ,將點陣圖中的 1 個值轉換為 rowids( 步驟 2) ,然後使用 rowids customers 表中獲取行 ( 步驟 1):

8.4.3 點陣圖索引單值 (Bitmap Index Single Value)

這種訪問路徑使用點陣圖索引查詢單個鍵值。

8.4.3.1 優化器 何時 考慮點陣圖索引單值

當謂詞包含相等運算子時,優化器將考慮此訪問路徑。

8.4.3.2 點陣圖索引單值的工作原理

查詢掃描單個點陣圖以查詢包含1 值的位置。資料庫將 1 值轉換為 rowids ,然後使用 rowids 查詢行。

資料庫只需要處理一個點陣圖。例如,下表表示sh.customers.cust_martin_status 列中 widown 值的點陣圖索引(兩個點陣圖)。為了滿足對狀態為 widown 的客戶的查詢,資料庫可以搜尋 widown 點陣圖中的每個 1 值,並找到相應行的 rowid

8.4.3.3 點陣圖索引單值:示例

在本例中,優化器選擇點陣圖索引單值操作來滿足使用相等謂詞的查詢。

查詢sh.customers 表將選擇所有喪偶客戶:

SELECT *

FROM customers

WHERE cust_marital_status = 'Widowed';

以下計劃顯示,資料庫使用客戶點陣圖索引中的喪偶鍵讀取條目(步驟3 ),將點陣圖中的 1 值轉換為 rowids (步驟 2 ),然後使用 rowids 從客戶表獲取行(步驟 1 ):

8.4.4 點陣圖索引範圍掃描 (Bitmap Index Range Scans)

這種訪問路徑使用點陣圖索引查詢一系列值。

8.4.4.1 優化器 何時 考慮點陣圖索引範圍掃描

當謂詞選擇一系列值時,優化器將考慮此訪問路徑。

掃描中的範圍可以在兩側有界,也可以在一側或兩側無界。優化器通常為選擇性查詢選擇範圍掃描。

8.4.4.2 點陣圖索引範圍掃描的工作原理

此掃描的工作原理與B 樹範圍掃描類似。

例如,下表表示sh.customers.cust_year_of_birth 列的點陣圖索引中的三個值。如果查詢請求 1917 年之前出生的所有客戶,則資料庫可以掃描此索引以查詢低於 1917 年的值,然後獲取具有 1 的行的 rowid

8.4.4.3 點陣圖索引範圍掃描:示例

本例使用範圍掃描來選擇在一年前出生的客戶。

查詢sh.customers 表可以選擇 1918 年以前出生的客戶的姓名:

SELECT cust_last_name, cust_first_name

FROM customers

WHERE cust_year_of_birth < 1918

以下計劃顯示,資料庫獲取低於1918 cust year 出生 鍵值 的所有點陣圖(步驟3 ),將點陣圖轉換為 rowid (步驟2 ),然後獲取行(步驟 1 ):

8.4.5 點陣圖合併 (Bitmap Merge)

此訪問路徑合併多個點陣圖,結果返回單個點陣圖。點陣圖合併由執行計劃中的點陣圖合併操作指示。

8.4.5.1 優化器考慮點陣圖合併時

優化器通常使用點陣圖合併來合併從點陣圖索引範圍掃描生成的點陣圖。

8.4.5.2 點陣圖合併的工作原理

合併在兩個點陣圖之間使用布林或運算。結果點陣圖選擇第一個點陣圖中的所有行,加上每個後續點陣圖中的所有行。

查詢可以選擇1918 年以前出生的所有客戶。以下示例顯示了三個 customers.cust_year_of_birth keys:1917 1916 1915 的示例點陣圖。如果任何點陣圖中的任何位置有 1 ,則合併的點陣圖在同一位置有 1 。否則,合併點陣圖的值為 0

結果點陣圖中的1 值對應於包含值 1915 1916 1917 的行。

8.4.5.3 點陣圖合併:示例

此示例顯示資料庫如何合併點陣圖,以使用範圍謂詞優化查詢。

查詢sh.customers 表可以選擇 1918 年以前出生的女性客戶的姓名:

SELECT cust_last_name, cust_first_name

FROM customers

WHERE cust_gender = 'F'

AND cust_year_of_birth < 1918

以下計劃顯示資料庫獲得所有的點陣圖cust_year_of_birth 鍵低於 1918( 步驟 6), 然後合併這些點陣圖使用或邏輯建立一個點陣圖 ( 步驟 5) 。資料庫獲取一個點陣圖 cust_gender 關鍵的 F( 步驟 4), 然後執行一個操作這兩個點陣圖。結果是一個單一的點陣圖,包含 1 個請求行的值 ( 步驟 3)

8.5 聚簇表 訪問路徑

Table Cluster Access Paths

聚簇表 是一組共享公共列並在相同塊中儲存相關資料的表。當對錶進行叢集化時,單個資料塊可以包含來自多個表的行。

8.5.1 聚簇 掃描

聚簇索引 是使用索引定位資料的表叢集。

叢集索引是叢集鍵上的一個B 樹索引。叢集掃描從儲存在 聚簇索引 中的表中檢索具有相同叢集鍵值的所有行。

8.5.1.1 優化器 何時 考慮 聚簇 掃描

當查詢訪問索引叢集中的表時,資料庫將考慮叢集掃描。

8.5.1.2 聚簇 掃描的工作原理

聚簇索引 中,資料庫將具有相同叢集鍵值的所有行儲存在相同的資料塊中。

例如,如果hr . employees2 hr.departments2 表被聚集在 emp_dept_cluster 中,如果叢集鍵是 department_id ,那麼資料庫將 department 10 中的所有員工儲存在同一個塊中, department 20 中的所有員工儲存在同一個塊中,以此類推。

B-tree 聚簇 索引將叢集鍵值與包含資料的塊的資料庫塊地址(DBA) 關聯起來。例如, key 30 的索引項顯示了包含 department 30 員工行的 block 的地址 :

30,AADAAAA9d

當使用者請求 聚簇表 中的行時,資料庫掃描索引以獲得包含這些行的塊的dba 。然後, Oracle 資料庫根據這些 dba 定位行。

8.5.1.3 聚簇掃描 :示例

此示例將employees departments 表聚集在 department _ id 上列,然後查詢單個部門的群集。

作為使用者hr ,可以在叢集中建立 聚簇表 聚簇 索引和表,如下所示 :

CREATE CLUSTER employees_departments_cluster

 (department_id NUMBER(4)) SIZE 512;

CREATE INDEX idx_emp_dept_cluster

 ON CLUSTER employees_departments_cluster;

CREATE TABLE employees2

 CLUSTER employees_departments_cluster (department_id)

 AS SELECT * FROM employees;

CREATE TABLE departments2

 CLUSTER employees_departments_cluster (department_id)

 AS SELECT * FROM departments;

您可以查詢部門30 中的員工,如下所示:

SELECT *

FROM employees2

WHERE department_id = 30;

為了執行掃描,Oracle 資料庫首先通過掃描 聚簇 索引獲得描述部門30 的行的 rowid (步驟 2 )。然後, Oracle 資料庫使用這個 rowid 定位 employees2 中的行(步驟 1

8.5.2 雜湊掃描 (Hash Scans)

雜湊 聚簇 類似於索引 聚簇 ,只是索引鍵替換為 雜湊 函式。不存在單獨的索引 聚簇

雜湊 聚簇 中,資料是索引。資料庫使用雜湊掃描根據雜湊值定位 雜湊 聚簇 中的行。

8.5.2.1 優化器 何時 考慮雜湊掃描

當查詢訪問 雜湊 聚簇 中的表時,資料庫將考慮 雜湊 掃描。

8.5.2.2 雜湊掃描的工作 原理

雜湊 聚簇 中,具有相同 雜湊 值的所有行都儲存在相同的資料塊中。

要執行叢集的 雜湊 掃描,Oracle 資料庫首先通過向語句指定的叢集鍵值應用 雜湊 函式來獲得 雜湊 值。然後,Oracle 資料庫掃描包含具有該 雜湊 值的行的資料塊。

8.5.2.3 雜湊 掃描:示例

此示例對department_id 列上的 employees departments 表進行 雜湊 ,然後查詢叢集中的單個部門。在叢集中建立雜湊叢集和表,如下所示:

CREATE CLUSTER employees_departments_cluster

 (department_id NUMBER(4)) SIZE 8192 HASHKEYS 100;

CREATE TABLE employees2

 CLUSTER employees_departments_cluster (department_id)

 AS SELECT * FROM employees;

CREATE TABLE departments2

 CLUSTER employees_departments_cluster (department_id)

 AS SELECT * FROM departments;

您可以查詢部門30 中的員工,如下所示:

SELECT *

FROM employees2

WHERE department_id = 30

為了執行 雜湊 掃描,Oracle 資料庫首先通過對鍵值 30 應用 雜湊 函式來獲取 雜湊 值,然後使用該 雜湊 值掃描資料塊並檢索行(步驟1 )。

歡迎關注我的微信公眾號"IT小Chen",共同學習,共同成長!!!

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29785807/viewspace-2679193/,如需轉載,請註明出處,否則將追究法律責任。

相關文章