☕ NEW! 完成新手任務即可參加抽獎!LINE 星巴克禮券等你拿,名額有限!        🎉 推廣活動:邀請好友註冊 DevLearn,累積推薦抽 LINE 星巴克禮券! 活動詳情 →        🔥 活動期間 2026/4/1 - 5/31 |已有 0 人參加       
sql 中級

INDEX 索引

什麼是索引?

比喻:索引就像書本的目錄 📑

一本 500 頁的書,你要找「第三章」—— 沒有目錄 → 一頁一頁翻(Full Table Scan) 有目錄 → 直接翻到第 87 頁(Index Scan)

索引是資料庫用來加速查詢的資料結構。


建立索引

-- 在 Students 的 Email 欄位建立索引
CREATE INDEX idx_students_email    -- ← 索引名稱(慣例:idx_表_欄位)
ON Students (Email);               -- ← 在哪個表的哪個欄位

-- 在 Orders 表建立複合索引
CREATE INDEX idx_orders_customer_date
ON Orders (CustomerId, OrderDate); -- ← 多欄位組合索引

逐行解析:

CREATE INDEX idx_students_email    -- 建立索引,取名 idx_students_email
ON Students (Email)                -- 在 Students 表的 Email 欄位上
                                   -- 之後 WHERE Email = '...' 會變快

索引的效果

-- 沒有索引:掃描全表(100 萬筆逐筆比對)
SELECT * FROM Students WHERE Email = 'test@gmail.com';
-- 可能需要 500ms

-- 建立索引後:直接定位
CREATE INDEX idx_students_email ON Students (Email);
SELECT * FROM Students WHERE Email = 'test@gmail.com';
-- 只需要 1ms

索引類型

B-Tree 索引(預設)

-- 適合:等值查詢、範圍查詢、排序
CREATE INDEX idx_age ON Students (Age);

-- 這些查詢都能用到 B-Tree 索引:
WHERE Age = 20          -- 等值
WHERE Age > 18          -- 範圍
WHERE Age BETWEEN 20 AND 25  -- 範圍
ORDER BY Age            -- 排序

唯一索引

-- 確保值不重複(自動作為約束)
CREATE UNIQUE INDEX idx_email_unique
ON Students (Email);

-- UNIQUE 約束其實就是建立唯一索引
ALTER TABLE Students ADD CONSTRAINT uq_email UNIQUE (Email);

部分索引(Partial Index)

-- 只對「有效」的資料建索引
CREATE INDEX idx_active_students
ON Students (Name)
WHERE IsActive = true;     -- ← 只索引 IsActive=true 的列

-- 適合:大部分查詢都只找 IsActive=true 的資料
-- 索引更小、更快

複合索引

CREATE INDEX idx_dept_score
ON Students (Department, Score);

-- ✅ 這些查詢能用到:
WHERE Department = '資工系'                    -- 左前綴匹配
WHERE Department = '資工系' AND Score > 80     -- 兩欄都用到
ORDER BY Department, Score                     -- 排序

-- ❌ 這個用不到:
WHERE Score > 80                               -- 沒有用到最左邊的欄位

💡 最左前綴原則:複合索引 (A, B, C),只有從 A 開始的查詢才能用到。


何時該建索引?

✅ 應該建索引

-- 1. WHERE 經常查詢的欄位
WHERE Email = '...'          -- 頻繁查詢 → 建索引

-- 2. JOIN 的連接欄位
ON Orders.CustomerId = Customers.Id  -- 外鍵欄位 → 建索引

-- 3. ORDER BY 的排序欄位
ORDER BY CreatedAt DESC      -- 頻繁排序 → 建索引

-- 4. UNIQUE 約束的欄位
-- 自動有索引

❌ 不應該建索引

-- 1. 很少查詢的欄位
-- 2. 經常大量 INSERT/UPDATE 的表(索引會拖慢寫入)
-- 3. 值很少變化的欄位(如 Gender 只有男/女,索引效果差)
-- 4. 資料量很小的表(直接全表掃描就很快了)

查看和管理索引

-- 查看表的所有索引(PostgreSQL)
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'students';

-- 刪除索引
DROP INDEX idx_students_email;

-- 查看查詢是否有用到索引
EXPLAIN ANALYZE
SELECT * FROM Students WHERE Email = 'test@gmail.com';
-- 結果會顯示 Index Scan 或 Seq Scan(全表掃描)

小結

概念 說明
索引 加速查詢的資料結構
B-Tree 預設索引,適合等值/範圍/排序
唯一索引 確保不重複
複合索引 多欄組合,注意最左前綴
部分索引 只索引部分資料
代價 加速讀取,但拖慢寫入

💡 大家的想法 · 0

載入中...
💬 即時聊天室 🟢 0 人在線
😀 😎 🤓 💻 🎮 🎸 🔥
➕ 新問題
📋 我的工單
💬 LINE 社群
🔒
需要註冊才能使用此功能
註冊帳號即可解鎖測驗、遊戲、簽到、筆記下載等所有功能,完全免費!
免費註冊