SQL 的效能問題和 SQL 本身一樣古老,甚至有人主張「SQL 天生就慢」。這在 SQL 剛問世的年代或許成立,如今已經不是事實——但效能問題依然層出不窮。為什麼?
抽象化的極限#
SQL 大概是最成功的第四代程式語言(4GL, fourth-generation programming language),它最大的優勢在於把「要什麼」和「怎麼做」徹底分離。一段 SQL 敘述只是描述所需的資料,完全不指示取得資料的手段:
SELECT date_of_birth
FROM employees
WHERE last_name = 'WINAND'這段查詢讀起來就像一句英文。撰寫 SQL 通常不需要理解資料庫或儲存系統(磁碟、檔案等)的內部運作,不必告訴資料庫要開哪個檔案、怎麼找到目標列。許多開發者有多年 SQL 經驗,卻對資料庫內部的處理所知甚少。
問題就出在這裡:關注點分離在 SQL 中運作得極好,卻不完美——它的極限就是效能。
依定義,SQL 敘述的作者不需要關心資料庫如何執行它,因此看似不必為執行緩慢負責。但經驗證明恰恰相反:作者必須懂一點資料庫,才能預防效能問題。
索引是開發任務,不是維運任務#
事實證明,開發者唯一需要學會的就是如何建索引。資料庫索引本質上是一項開發工作,理由很單純:
- 正確建索引所需的最重要資訊,不是儲存系統設定,也不是硬體配置。
- 最重要的資訊是「應用程式如何查詢資料」——也就是存取路徑(access path)。
- 這份知識對資料庫管理員(DBA, database administrator)或外部顧問而言並不容易取得,得花不少時間逆向工程應用程式才能拼湊出來;開發端卻本來就握有它。
本書只涵蓋開發者需要知道的索引知識——不多也不少。更精確地說,本書只談最重要的索引型態:B-tree 索引。
B-tree 索引在多數資料庫中的運作方式幾乎相同。本書僅採用 Oracle® 資料庫的術語,但原理同樣適用於其他資料庫;書中的旁註會補充 MySQL、PostgreSQL 與 SQL Server® 的相關資訊。
本書結構#
本書的結構是為開發者量身打造的:多數章節對應 SQL 敘述的某個特定部分。
- 第 1 章 — 索引的解剖:唯一不專門談 SQL 的章節,講的是索引的基本結構。理解索引結構是後續章節的前提,別跳過。全章僅約八頁,讀完就能理解「慢索引」現象。
- 第 2 章 — Where 子句:全書主體,火力全開。從最簡單的單欄查找,到範圍查詢與
LIKE這類特殊情況,涵蓋 where 子句的所有面向。學會這些技巧,寫出的 SQL 會快上許多。 - 第 3 章 — 效能與擴展性:關於效能量測與資料庫擴展性的小小離題。看看為什麼加硬體不是解決慢查詢的最佳方案。
- 第 4 章 — Join 運算:回到 SQL,說明如何用索引做出快速的資料表 join。
- 第 5 章 — 資料叢集化:你是否想過「只選一個欄位」和「選出所有欄位」有何差別?答案在此,還附帶一個效能更上一層樓的技巧。
- 第 6 章 — 排序與分組:連 order by 和 group by 都能用上索引。
- 第 7 章 — 部分結果:當你不需要完整結果集時,如何從「管線化(pipelined)」執行中獲益。
- 第 8 章 — 修改資料:索引如何影響寫入效能?索引不是免費的——請明智地使用。
- 附錄 A — 執行計畫:如何詢問資料庫「你是怎麼執行這段敘述的」。