Oracle 11g Release 1 (11.1) 查询优化器的访问路径
http://docs.oracle.com/cd/B28359_01/server.111/b28274/optimops.htm#i82080
?
本文內容
- 全表掃描(Full Table Scans)
- 物理 ID 掃描(Rowid Scans)
- 索引掃描(Index Scans)
- 聚簇訪問(Cluster Access)
- 哈希訪問(Hash Access)
- 采樣表掃描(Sample Table Scans)
- 查詢優化器如何選擇訪問路徑
- 備注
?
訪問路徑(Access paths)是從數據庫檢索數據的方式。一般地,索引訪問路徑(index access paths)用于檢索表數據行一個小的子集語句,而當訪問表的一個大部分時,全表掃描(full scans)更有效率。在線事務處理(Online transaction processing,OLTP)應用程序,它是由具有高選擇性的短期運行的 SQL 語句組成,通常用索引訪問路徑。另一個方面,決策支持系統(Decision support systems)傾向于使用分區表,執行相關分區的全表掃描。
?
全表掃描
全表掃描讀取表的所有行,并過濾掉那些不符合選擇條件的行。執行全表掃描期間,表中高水位線(high water mark,HWM)以下的所有數據塊都會被掃描。高水位以下的所有數據表示已使用的空間數量(插入數據后),或收到數據已被格式化的空間(插入數據后,再刪除的空間)。檢查每個行是否滿足 WHERE 子句。
當Oracle 執行全表掃描時,順序地讀取塊。因為塊是相鄰的,所以 I/O 調用要比單塊大,加速了處理。讀取調用大小的范圍從 1 個塊到初始化參數 DB_FILE_MULTIBLOCK_READ_COUNT 指定的塊數量。使用多塊讀取意味著,全表掃描以很高的效率執行。每個塊只被讀取一次。
為什么全表掃描對于訪問大數據量更快?
當訪問表中塊的很大一部分時,全表掃描要比索引范圍掃描更劃算。這是因為,全表掃描可以使用更大的 I/O 調用,而次數少卻較大的 I/O 調用要比次數多卻小的調用代價更小。
優化器何時使用全表掃描?
優化器在以下情況使用全表掃描:
- 沒有索引
若查詢不能使用任何現存的索引,則使用全表掃描。例如,如果查詢中有一個在已索引列上使用函數,那么,優化器就不能使用索引,而是使用全表掃描。
如果你需要使用索引來進行不依賴大小寫的檢索,那么,或者在檢索中不允許大小寫混合,或是在檢索列上創建一個基于函數的索引,如 UPPER(last_name)。參考 “使用基于函數索引的性能”。
- 大數據量
若優化器認為,查詢會訪問表中的大多數塊,則使用全表掃描,即使有索引可用。
- 小的表
若一個表高水位線以下包含比 DB_FILE_MULTIBLOCK_READ_COUNT 參數小塊,它們可以在一個單 I/O 調用讀取,那么全表掃描比索引范圍掃描更劃算,而不管可被訪問表的其他部分,或現在的索引。
- 高并行度
一個表的高并行度會使優化器傾向于全表掃描,而不是范圍掃描。檢查 ALL_TABLES 表的 DEGREE 列以確定并行程度。
全表掃描提示
使用 FULL(table alias) 來命令優化器使用全表掃描。參考“指示訪問路徑”。
可以使用 CACHE 和 NOCACHE 指示已檢索的塊是否放在緩沖區緩存。CACHE 命令優化器,當執行全表掃描時,把已檢索的塊放在緩沖區高速緩存 LRU 列表最近使用的末尾。
小的表 1 根據下表的準則自動緩存。
表 1 緩存表的準則
| 表大小 | 大小準則 | 緩存 |
| 小 | 塊的數量大于 20 個,或已緩存的塊達到總數的 2%,不管多大 | 如果 STATISTICS_LEVEL 設置為 TYPICAL 或更高,Oracle 確定是否依賴表的掃描記錄緩存一個表。只有之后表掃描可能查找已緩存的塊,表才會被緩存。若 STATISTICS_LEVEL 設置成 BASIC,則表不被緩存。 |
| 中 | 比上面的大,并且已緩存的塊小于總數的 10% | Oracle 確定是否基于表的掃描和負載記錄緩存一個表。只有之后的掃描可能查找已緩存的塊,才會緩存表。 |
| 大 | 已緩存的塊大于總數的 10% | 不被緩存。 |
對于用 CACHE 屬性創建或變更的表,禁用小表的自動緩存。
并行查詢的執行
當需要全表掃描時,通過多并行執行服務來掃描表已提高響應時間。并行查詢通常用于低并發數據的數據倉庫環境。
?
物理 ID(Rowids)掃描
一個行的物理 ID 指定數據文件(datafile),以及包含行的數據塊和塊中行位置的數據塊。通過指定行的物理 ID 定位行是檢索一個單獨行的最快方式,因為在數據庫中指定了行的精確定位。為了通過物理 ID 訪問一個表,Oracle 首先獲得已選定行的物理 ID,無論是從語句的 WHERE 子句,還是通過一個或多個表索引的索引掃描。之后,Oracle 基于它們的物理 ID 在表中定位每個選擇的行。
優化器何時使用 Rowids
一般地,這是從一個索引檢索物理 ID 后的第二步。訪問的表可能在語句中要求任何列,而這些列并不在索引中。
通過物理 ID 訪問不需要按照每個索引掃描。若索引包含語句需要的所有列,則通過物理 ID 訪問可能不會發生。
?
索引掃描
此方法中,使用語句中指定的已索引的列的值,通過遍歷索引來檢索行。索引掃描基于索引中的一個或多個值,從索引中檢索數據。要執行一個索引掃描,Oracle 為已建立索引列的值檢索索引。若語句僅僅訪問索引列,則 Oracle 從索引直接讀取已索引的列值,而不是從表。
索引不僅包含索引值,而且也包含表中具有該值的行的物理 ID。因此,若語句訪問其他沒有索引的列,則 Oracle 通過物理 ID 或聚簇掃描查找表中的行。
以下是索引掃描類型:
- 通過塊訪問 I/O,不是行
- 索引唯一掃描(Index Unique Scans)
- 索引范圍掃描(Index Range Scans)
- 索引訪問遞減掃描(Index Range Scans Descending)
- 索引濾過掃描(Index Skip Scans)
- 全表掃描(Full Scans)
- 快速全表索引掃描(Fast Full Index Scans)
- 索引連接(Index Joins)
- Bitmap 索引(Bitmap Indexes)
?
聚簇訪問
聚簇掃描用于從存儲在已索引聚簇的表中檢索具有相同聚簇鍵值的所有行。要執行聚簇掃描,Oracle 首先通過掃描聚簇索引,獲得已選定行的物理 ID。再基于物理 ID 定位行。
?
哈希訪問
哈希掃描用于基于哈希值在哈希聚簇中定位行。在哈希聚簇中,具有相同哈希值的所有行被存儲在相同的數據塊。要執行哈希掃描,Oracle 首先通過把一個哈希函數應用到一個聚簇鍵值,來獲得哈希值。再掃描包含哈希值的行所在數據塊。
?
采樣表掃描
采樣(隨機)表掃描從一個采樣表或是一個復雜的 SELECT 語句檢索隨機的采樣數據。當 FROM 語句包含 SAMPLE 子句或 SAMPLE BLOCK 子句時,使用該訪問路徑。當用 SAMPLE 子句采樣數據時,要執行一個采樣表掃描,Oracle 在表中讀取一個指定的行百分比。當用 SAMPLE BLOCK 子句采樣塊時,Oracle 讀取一個指定的表塊的百分比。
?
查詢優化器如何選擇訪問路徑
查詢優化器基于下面因素選擇一個訪問路徑:
- 語句可用的訪問路徑
- 通過每個訪問路徑,或訪問路徑的結合,評估執行語句的代價
要選擇一個訪問路徑,優化器首先通過檢查 WHERE 子句和 FROM 子句的條件來確定哪個訪問路徑可用。然后,優化器使用訪問路徑產生一套可能的執行計劃,并通過索引、列和訪問表語句的統計信息來評估每個執行計劃的代價。最后,優化器選擇具有最小代價的執行計劃。
當選擇一個訪問路徑時,查詢優化器受下面影響:
- 優化器指示
可以指定優化器使用指定的訪問路徑,除了包含 SAMPLE 或 SAMPLE BLOCK 的 FROM 子句。
- 統計信息
例如,若一個表自創建以來,沒有分析過,并且其高水位線下(HWM)的塊小于參數 DB_FILE_MULTIBLOCK_READ_COUNT,則優化器認為,這個表比較小,并使用全表掃描。查看 ALL_TABLES 表中的 LAST_ANALYZED 和 BLOCKS 列來檢查統計信息。
?
備注
高水位線(high water mark,HWM)
Oracle 在邏輯存儲上分為 4 個粒度——表空間、段、區和塊。
- 塊是最小的存儲單位(8K)。Oracle 的每次I/O操作也是按塊的。即當 Oracle 讀數據時,是讀取多少個塊,而不是多少行。
- 區是由一系列相鄰的塊組成,這是 Oracle 分配空間的基本單位。比如,當創建一個表時,Oracle 會分配一個區的空間給該表。當該區滿了后,Oracle 以區為單位進行擴展,而不是塊。
- 段是由一系列的區組成。一般地,當創建一個對象時(表或索引),Oracle 會分配一個段給該對象。某種意義上,段是某種特定的數據。如 CREATE TABLE 時,Oracle 為表創建數據段,CREATE INDEX 時,Oracle 還會分配一個段,只是這個段是索引段。
- 表空間包含了段、區和塊。表空間數據物理上儲存在其所在的數據文件中。
Oracle 用高水位線(high water mark,HWM)來界定一個段中使用的塊和未使用的塊。
比如,當創建一個表時,Oracle 為該對象分配一個段。即使還未插入任何記錄,也至少有一個區被分配。第一個區的第一個塊稱為段頭(SEGMENT HEADE)。段頭儲存了一些信息,如 HWM 信息。HWM 位于第 2 個塊。當塊放不下新數據,Oracle 用 HWM 之上的塊存儲,同時,HWM 向上移。當不斷插入數據時,HWM 會不斷上移。這樣,HWM 之下表示使用過的塊,HWM 之上的就表示已分配但未使用過的塊。如圖 1 所示:
圖 1 插入數據的高水位線
其中,灰色方塊表示數據行。
HWM 在插入數據時,會向上移,但刪除數據時不會往下移。如圖 2 所示:
圖 2 刪除數據的高水位線
Oracle 高水位線,就像水庫的水位,當漲水時,水位往上移。當水退后,最高水位的痕跡還是清淅可見。
總結
以上是生活随笔為你收集整理的Oracle 11g Release 1 (11.1) 查询优化器的访问路径的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 读出文件中的数据
- 下一篇: linux上利用crontab定时备份p