題目與範圍
資料表按日追加寫入,但 account_id 未聚簇;等值查詢通常命中遠低於 1% 的列。請說明如何在不改變結果下跳過列群組或頁面、如何驗證讀寫端支援,以及何時元資料和寫入成本不值得。容量和選擇率是面試假設,核心能力是機率型檔案布局最佳化,因此分類為 data。
面試官考察點
優秀回答會區分機率成員測試與精確索引:負結果證明不存在,正結果只表示需要保留候選。還應說明目標實作的過濾粒度和儲存位置,處理 null 與編碼,並保留普通讀取回退。必須提出相同快照、快取條件和讀取器版本的對照實驗。
先釐清的問題
- 線上 Parquet 寫入器和讀取器及其版本是否支援 Bloom filter?
- 謂詞只有等值,還是要支援
IN清單和鍵值正規化? - 目前實作按欄位區塊、列群組還是頁面附加過濾器?
- 每個受保護單元的基數分布和目標誤報率是多少?
- 舊讀取器能否忽略元資料並回傳相同結果?
- 檔案是否不可變,壓縮和重寫會帶來多少持續 CPU 成本?
30 秒答題框架
「先確認端到端讀寫支援,並檢查樣本 footer 中過濾器偏移與大小。只對高選擇性的等值欄位啟用,依真實分布設定誤報目標,並保留停用過濾器的對照組。灰度期間比較讀取單元、位元組、CPU、延遲、過濾器位元組和準確結果。只有確定的負結果才能跳過;正結果仍執行精確謂詞。若讀取器不支援或查詢很寬,繼續普通 Parquet 過濾。」
分步作答
步驟 1:確認能力和粒度
閱讀 Apache Parquet Bloom-filter 規範及目前函式庫的實作狀態。驗證寫入器持久化過濾器、讀取器按目標謂詞消費過濾器,並記錄偏移、長度和保護的資料單元;不能假設所有引擎粒度一致。
步驟 2:選擇欄位並確定容量
估計每個受保護單元的基數和查詢選擇率。依據明確的誤報目標確定容量,再測量記憶體、footer 增長和寫入 CPU。太小會產生大量正結果,太大則增加元資料 I/O,卻未必改善寬掃描。
步驟 3:保持機率語義
查詢值得到負成員結果時可安全跳過單元;得到正結果只代表「可能存在」,讀取器仍須解碼並執行精確謂詞。不能直接用 Bloom filter 回傳空結果,並分別測試 null 與鍵值正規化。
步驟 4:帶對照灰度
先為一個分割區或檔案批次寫入過濾器,同時保留等價的無過濾器批次。對同一快照、工作負載、並行度和讀取器版本執行點查找、長 IN、缺失鍵、熱門鍵及低選擇率查詢。
步驟 5:定義驗收與回滾
記錄測試單元數、負結果、誤報、讀取單元、讀取位元組、過濾器位元組、CPU、p50/p95 延遲和寫入吞吐。比較過濾器開關兩組的完整結果、計數和聚合;若結果不同、元資料開銷升高或跳過率無意義,停止寫入或停用消費。
參考答案
「當等值謂詞選擇性高且值分散時,Bloom filter 有價值。我會先驗證部署中的 Parquet 讀寫器支援,檢查過濾器偏移和粒度,並按真實誤報目標定容量。在灰度分割區設定無過濾器對照,控制快照、快取和資源。負成員結果可跳過單元,正結果必須執行精確謂詞。驗收要求結果完全一致,同時讀取單元、位元組和 p95 下降,並監控 footer 增長、CPU 與寫吞吐。不支援的舊讀取器繼續普通讀取,發布可回退。」
常見錯誤
- 把「可能包含」當成確定包含 → 會遺失匹配列 → 正結果後解碼執行精確謂詞。
- 預設所有讀取器支援 → 元資料被忽略或行為不一致 → 按版本建立讀寫矩陣。
- 按全表基數定容量 → 區域單元分布不同 → 測量每個受保護單元的基數。
- 只測點查找 → 寬掃描可能承擔額外開銷 → 加入低選擇率負對照。
- 使用不同快照比較 → 結果和快取效應混雜 → 固定快照、資源和工作負載。
- 忽略 null 與正規化 → 邊界語義未驗證 → 涵蓋 null、大小寫、編碼和
IN。
追問
追問 1:誤報會改變正確性嗎?
不會,誤報只增加讀取。只有把正結果當證明,或在元資料損壞時錯誤信任負結果,才會造成正確性問題。
追問 2:何時不值得寫 Bloom filter?
全表掃描、低選擇率、小檔案以及讀取器忽略過濾器時收益很小。應比較過濾器位元組、寫入 CPU 與實際跳過收益。
追問 3:如何驗證缺失鍵?
選取快照中不存在的鍵,確認多數受保護單元回傳負結果,再比較開關過濾器時完整查詢均為空。
追問 4:讀取器不支援怎麼辦?
讀取器應忽略可選元資料並執行普通列群組或頁面過濾。保留相容性測試,不能把過濾器存在作為正確性的前置條件。