在數據庫內核(InnoDB、PostgreSQL 等),**99% 以上的索引查找**都依賴二分查找:
> vs >=)一個錯誤的二分查找會導致數據遺漏、死循環、越界訪問,嚴重影響正確性與效能。
頁面可能無用戶記錄(全刪除未合併),low=high=0。若直接計算 mid 訪問記錄 → **邏輯錯誤/段錯誤**。
內核做法: 進入二分前判斷 PAGE_GET_N_RECS(page) == 0 直接返回「未找到」。
mid = (low + high) / 2 — low+high 可能溢出(32 位系統)。mid = low + (high - low) / 2 — **數學等價但永不溢出**,保證 low < mid < high。InnoDB 選擇: 頁內記錄數有限(8KB/16KB 頁),low+high 不會溢出,**為簡潔採用寫法 A**;但通用庫建議寫法 B。
所有主流數據庫內核(InnoDB、PostgreSQL、SQLite)均採用迭代實現。
索引頁常有大量重複鍵值(如用戶訂單)。
naïve 做法: 二分找到任一等值 → 順序掃描至首/尾,**最壞 O(N)**。
內核做法: 將「比較結果」按 Search Mode** 糾正,使等值仍繼續二分:
| Search Mode | SQL 對應 | 等值時動作 |
|---|---|---|
| PAGE_CUR_G (1) | > | 視為「大於」→ low = mid,繼續向右找**最後一個等值** |
| PAGE_CUR_GE (2) | >=, = | 視為「小於」→ high = mid,繼續向左找**第一個等值** |
| PAGE_CUR_L (3) | < | 視為「小於」→ high = mid,向左找**第一個等值** |
| PAGE_CUR_LE (4) | <= | 視為「大於」→ low = mid,向右找**最後一個等值** |
如此,**全程 O(log N) 完成首/尾定位**,無須退化掃描。
/* 運算符 includeKey forward compare result: 1 0 -1 */ =================================================================== >= 1 1 | 1 -1 -1 = 1 1 | 1 -1 -1 > 0 1 | 1 1 -1 < 0 0 | 1 -1 -1 <= 1 0 | 1 1 -1 ===================================================================
includeKey:是否包含邊界值(>=/<= 為 1)forward:掃描方向(1=正向,0=反向)low/high 移動。mid = low + (high - low) >> 1(位運算更快)。while (low < high) 或 low <= high,視具體收斂邏輯。switch 映射,避免分支預測失敗。low 或 high 作為插入/掃描起始槽位。二分查找看似簡單,**邊界條件、等值語義、溢出安全、迭代實現**四大維度決定了數據庫內核的穩健度。參考 InnoDB page_cur_search_with_match、PostgreSQL _bt_search 等經典實現,構建屬於自己的高效、正確的二分查找組件。