Oracle學習筆記(一)——B-Tree索引

来源:https://www.cnblogs.com/kungfupanda/archive/2020/04/26/12776710.html
-Advertisement-
Play Games

https://blog.csdn.net/biww620/article/details/73003880 目錄是索引的一個最好的例子,每條目錄包含對應章節的標題和頁碼,類比索引的每條索引項包含了數據記錄的某些鍵值組合併包含了對應數據塊的訪問路徑(rowid)。目錄的存在就是為了快速定位到感興趣的 ...


https://blog.csdn.net/biww620/article/details/73003880

 

  目錄是索引的一個最好的例子,每條目錄包含對應章節的標題和頁碼,類比索引的每條索引項包含了數據記錄的某些鍵值組合併包含了對應數據塊的訪問路徑(rowid)。目錄的存在就是為了快速定位到感興趣的內容,索引的存在也是問了加快對錶數據的隨機訪問。

        常常被提及的索引可能有單鍵索引、組合索引、唯一索引、B-Tree索引、點陣圖索引、函數索引、全局索引、局部索引等等。這裡只是列舉出鏡率較高的索引類型,並沒有去做嚴格的劃分,各類型間有重疊,比如函數索引可以是B-Tree索引也可以是點陣圖索引。在Oracle中索引和表一樣屬於邏輯結構中的段(segment)。每個索引都擁有獨立的結構,無論是從物理結構還是邏輯結構來看與其所關聯的表完全分開,即便索引失效也不會造成原有SQL無法執行,只是改變了執行計劃,降低了執行效率。

B-Tree索引
        查找樹有完全二叉樹、二叉查找樹、平衡二叉樹、紅黑樹,B-Tree,B+-Tree,B*-Tree等。對於二叉樹其目的是要將查詢複雜度控制在O(lgN)以內。(註:這裡的lgN表示log2N),查詢效率與樹的高度有關。在少量數據構造的二叉樹查詢是很高效的,但是在資料庫應用中,數據量巨大,如果構造二叉樹那麼樹的高度將也很巨大,勢必增加讀取索引節點的I/O次數,影響查詢效率。於是B-Tree挺身而出,在很大的數據量範圍內能夠保持B-Tree樹的層級不會增加。

圖片來自網路

從上圖中可以看出在oraccle中B-Tree索引具有以下結構特點:
B-Tree索引包含根節點(Root Node)、分支節點(Branch Node)和葉子節點(Leaf Node)。
索引樹高度一般都很低,上百億記錄的索引樹的高度也只有5,6層。
索引本身有序。葉子節點是一個雙向鏈表,因此可以按照索引的升序或降序進行索引掃描。
索引項包含鍵值信息和ROWID。索引項由索引頭部、索引列的長度、索引值以及對應記錄的rowid。其中唯一索引對應的rowid是唯一的,非唯一索引對應的rowid是可能有多個(多個rowid是有序的)。
索引列值全部為NULL的索引項是不會被記錄的。
B-Tree索引簡要分析
一、提高查詢效率
200w條記錄的表test_index_t1,查找條件col1 = 98765的記錄沒有索引的執行計劃如下:


在test_index_t1表的col1列添加索引
create index index_col1 on test_index_t1(col1);
再次執行查詢的執行計劃如下:


未建立索引時執行計劃是TABLE ACCESS FULL用時1100ms,建立索引後執行計劃是INDEX RANGE SCAN用時90ms,效率提高了10倍以上。這裡test_index_t1的數據量不大。如果是大數據量的表執行效率的差距會更加明顯。
二、索引樹高度較低
通過以下sql可以查詢索引的統計信息,其中BLEVEL表示索引樹的高度,高度為BLEVEL +  1
SELECT
index_name,
blevel,
leaf_blocks,
num_rows,
distinct_keys,
clustering_factor
FROM
user_ind_statistics
WHERE
table_name = UPPER('test_index_t1');

對於200w條記錄的表test_index_t1執行索引統計信息查詢後得到的結果為:

        可以看出BLEVEL = 2也就是說索引樹的高度為3。構建了記錄數分別為10條,20w條和300w條的表並建立相同的索引,索引樹高度分別為2,2,3。因此可以看出B-Tree索引的高度是比較低的,能夠在大數據量的情況下保證樹高度值很低。在通過索引執行查詢時一個層級往往就代表一次I/O操作,因此保持索引樹高度較低對查詢性能有很大的好處。
三、索引包含鍵值
       索引包含索引鍵值,單鍵或鍵組合,如果查詢所需的欄位均在索引項中則可以避免回表讀數,提高查詢性能。創建表test_index_t1包含三個欄位col1,col2,col3初始化為300w條記錄,並建立了(col1,col2)組合索引。
create index index_col1_col2 on test_index_t1(col1, col2);
1. 執行sql 
select col1 from test_index_t1 where col1 between 10 and 20;


2. 執行sql
select col1, col2 from test_index_t1 where col1 between 10 and 20;

 

3. 執行sql
select * from test_index_t1 where col1 between 10 and 20;

從上面三次查詢結果可以看出:
     (1) 三次執行SQL均用到了索引INDEX_COL1_COL2,索引執行方式為Index Range Scan
     (2) 第一次和第二次查詢(col1)、(col1、col2)均未回表讀數,而第三次查詢存在TABLE ACCESS BY INDEX ROWID回表讀數,原因是組合索引INDEX_COL1_COL2中不包含列col3,因此通過索引掃描得到最終記錄的rowid後還會根據rowid到表中讀取col3。
      總體來看,如果所需列包含於索引中那麼可以通過索引避免回表讀數從而提高查詢性能。但需要註意的是索引本身也有性能消耗,並不是包含的列越多越好。一般建議索引列不超過3個,從實際的經驗來看5,6個也還是可以接受。
四、索引本身有序
      在前面提到的索引結構中可以看出索引葉子結點本身是按照索引鍵升序排列,相當於一個雙向鏈表,可以進行升序或降序掃描。刪除test_index_t1表的索引,再執行查詢
select col1, col2 from test_index_t1 where col1 between 10 and 20 order by col1;


從執行計劃和統計信息中可以看出執行了排序過程並使用了記憶體空間。給test_index_t1表col1欄位加上索引後的執行計劃如下

        執行計划走索引後SORT ORDER BY不存在了。因此,如果因為排序導致查詢性能降低可以考慮在索引中包含需要排序的列,這樣利用索引本身的有序性可以避免排序帶來的性能損耗。
五、索引不保存索引鍵值全部為NULL的記錄
         這個特點跟count,sum/avg,max/min的執行計劃息息相關,可以總結為以下兩點:
COUNT/SUM/AVG必須在索引列為非空的情況下才可以走到索引。(建表是列指定為Not Null或為主鍵或在where條件中指明為is not null)。
MIN/MAX則不會受到空值的影響,均能走到索引。
表test_index_t1有300w條記錄,在col1上建立了索引,執行:
select count(1) from test_index_t1;


可以看出是走了全表掃描。在where條件中增加col1 is not null後的執行計劃為:

用INDEX FAST FULL SCAN的方式使用索引INDEX_COL1。最後col1添加屬性not null後的執行計劃為:

可以看出給列col1添加了not null屬性後執行計劃跟在where條件中指明is not null相同。這裡不再對sum/avg,min/max做驗證。
————————————————
版權聲明:本文為CSDN博主「biww620」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/biww620/java/article/details/73003880


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • dd:刪除百游標所在的一整行(常用)ndd:n為數字。刪除游標所在的向下n行,例如20dd則是刪除游標度所在的向下20行d1G:刪除游標所在到第一行的所有數據dG:刪除游標所在到最後一行的所有數據d$:刪除內游標所在處,容到該行的最後一個字元d0:那個是數字0,刪除游標所在到該行的最前面的一個字元x ...
  • VMware Workstation unrecoverable error: (vmx) Exception 0xc0000006 (disk error while paging) has occurred. A log file is available in等等 多方查找 解決辦法如下: 刪 ...
  • python代碼連接mysql資料庫 有bug(sql註入的問題): #pip3 install pymysql import pymysql user=input('user>>: ').strip() pwd=input('password>>: ').strip() # 建立鏈接 conn=p ...
  • 僅限於自己學習使用 新進公司,需要安裝jdk1.6,tomcat6, oracle和pl/sql 先是jdk1.6,安裝後配置環境變數,都在系統變數里,在cmd,分別打出 java -version,java,javac 這三個都需要打,出現問題就有可能是環境變數配置有問題. tomcat6,也是, ...
  • // 每個鏈表節點使用一個 ListNode 結構來表示typedef struct ListNode{ //前置節點 struct ListNode *prev; //後置節點 struct ListNode *next; //節點值 void *value; } ListNode; // typ ...
  • 2.1 SDS的定義 struct { //buf中已使用的位元組數,等於SDS所保存字元串的長度 int len; //buf中未使用的位元組長度 int free; //位元組數組,用於保存字元串 char[] buf; } 2.2 SDS與C字元串的區別 C字元串 SDS 獲取字元串長度的複雜度為 ...
  • 關鍵詞:version select version(); ...
  • 一、下載地址 Oracle Database 官方下載地址:https://www.oracle.com/database/technologies/oracle-database-software-downloads.html,打開後可以找個各個版本的下載文件。例如我的電腦是 Win10 64位, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...