CodeGym /課程 /SQL SELF /索引運作原理:資料結構與搜尋演算法

索引運作原理:資料結構與搜尋演算法

SQL SELF
等級 37 , 課堂 4
開放

今天我們要更深入聊聊索引的架構,看看它們底層到底怎麼跑的。其實搞懂索引的結構,不只可以知道為什麼查詢會變快,還能幫你針對不同需求挑最適合的索引。

講到索引結構,就是在說資料在索引裡是怎麼被組織起來,好讓搜尋變快。想像一下有個文件櫃。如果文件全部亂塞一堆,要找東西超麻煩。但如果櫃子是照字母順序排好,找資料就簡單多了。索引就是這樣:它們把資料排好,讓你可以超快找到想要的資訊。

B-TREE 索引結構

B-TREE(balanced tree — 平衡樹)是 PostgreSQL 裡最常用的索引類型。基本上,它是一種樹狀結構,資料被分在不同節點裡,搜尋時會從樹根一路往下找到葉子節點。

大概長這樣:

         樹根
          /       |       \
      節點 1    節點 2    節點 3
     /   \       |       /   \
葉子1 葉子2   葉子3  葉子4 葉子5

每個節點都會放關鍵值,幫助你導引搜尋。例如,如果樹根節點有 [10, 20, 30] 這些值:

  • 所有小於 10 的資料都在 葉子1。
  • 所有介於 1020 之間的資料在 葉子2,依此類推。

B-TREE 索引的優點:

  • 搜尋超快:搜尋複雜度是 O(log n),比線性搜尋快很多。
  • 很適合做範圍查詢(像是找所有介於 1050 之間的值)。

舉個例子: 假設我們有個 students 表格,裡面有個 age 欄位。當我們在這個欄位上建立 B-TREE 索引:

CREATE INDEX age_idx ON students (age);

PostgreSQL 會幫年齡值建一棵平衡樹,這樣你要找某個年齡或年齡範圍的學生就超快。

B-TREE 裡的搜尋演算法

當你下查詢時,PostgreSQL 會這樣用索引來找資料:

  1. 決定搜尋的 key(例如年齡 25)。
  2. 從樹根節點開始。
  3. 把 key 跟節點裡的值比對,然後走到對應的子節點。
  4. 重複第 3 步,直到走到葉子節點。
  5. 從葉子節點拿出對應 key 的資料。

查詢範例:

SELECT * FROM students WHERE age = 25;

索引會大幅減少要掃的資料量,讓搜尋變超快。

搜尋演算法與效能

索引能加速搜尋,是因為它們減少你要掃的資料筆數。沒索引時,PostgreSQL 會掃整張表(這叫 順序掃描,也就是 Seq Scan)。有索引時,會用 索引掃描Index Scan),快很多。

順序掃描 vs 索引掃描

  • 順序掃描(Seq Scan):

    • PostgreSQL 會讀每一筆資料,檢查查詢條件,然後回傳符合的資料。
    • 如果沒索引,或查詢幾乎涵蓋整張表,就會用這個。
  • 索引掃描(Index Scan):

    • PostgreSQL 會用索引先找到對應的資料,再去表格抓這些資料。
    • 如果表很大、查詢只要少量資料,這個超快。

舉例: 沒索引時查年齡

SELECT * FROM students WHERE age = 25;

結果可能要讀 100 萬筆資料。有 B-TREE 索引時,系統可能只要讀 100 筆。

索引結構對效能的影響

索引會加速,是因為它們讓你不用掃全部資料。像表裡有幾百萬筆,索引會把它們組織好,查詢時只要讀幾個節點,不用全表掃一遍。

搞懂索引結構很重要。知道索引怎麼運作,你就能理解為什麼有些查詢慢、怎麼讓它變快。

還有,選對索引也很關鍵。要查範圍用 B-TREE。要查陣列或 JSONB 用 GIN。選錯索引反而會拖慢資料庫。

實際範例

來看看索引怎麼幫我們工作。

排序用的索引

CREATE INDEX salary_idx ON employees (salary);
SELECT * FROM employees ORDER BY salary;

B-TREE 索引時,PostgreSQL 可以直接從索引拿出排序好的資料,不用再另外排序。

範圍查詢用的索引

CREATE INDEX price_idx ON products (price);
SELECT * FROM products WHERE price BETWEEN 100 AND 500;

B-TREE 索引可以很快找到落在指定範圍內的資料。

常見問題與小陷阱

為什麼不是每個欄位都該加索引? 索引會佔硬碟空間,而且每次 insert、update、delete 都要更新索引結構,會拖慢這些操作。所以只要在常查詢的欄位加索引就好。

什麼時候索引沒用? 如果查詢會抓到大部分資料(像 WHERE true),PostgreSQL 會選擇 Seq Scan,因為讀索引節點沒什麼幫助。

1
問卷/小測驗
索引入門,等級 37,課堂 4
未開放
索引入門
索引入門
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION