跳轉到

PostgreSQL JSONB Hot Predicate Anti-pattern

概念概覽

核心規則

核心知識

核心規則

查詢 hot path 上的 predicate 欄位(高頻 WHERE 條件)不應存放於 JSONB,即使 PostgreSQL 支援 JSONB expression index。

原因

  • JSONB expression index 有效,但 selectivity 和 vacuum 行為劣於原生欄位
  • 25M snapshot path 場景下,JSONB predicate 查詢不可接受(成本過高)
  • season_id 這類業務核心 predicate 若放 JSONB,schema 演進與 query planner 優化空間都受限

判斷標準

欄位是 hot predicate?
  ├─ 是 → 原生欄位 + B-tree index(必要時 partial index)
  └─ 否 → 可放 JSONB metadata(彈性 > 性能)

本案例

inventory 表缺少 season_iditem_secondary_type 原生欄位,導致 AUTO_CONVERT snapshot 查詢模型與實作完全對不上。修正路徑:加原生欄位 + 補 index,而非補 JSONB expression index。

經驗教訓

  • PostgreSQL 可對 JSONB 做 expression index,但這不代表 hot predicate 應該放 JSONB

  • schema 設計時 season_id 這類業務核心維度應從一開始就是原生欄位

  • 查詢模型(設計文檔)與實作 schema 對不上,通常根因是早期 schema 決策不完整

常見陷阱

  • 以「JSONB 有 expression index 支援」為由把 season_id 留在 metadata JSONB

  • 在 25M+ 行的 snapshot 表上用 JSONB predicate 掃描而不加原生欄位

最佳實踐

  • 新增原生欄位 season_id(NOT NULL,有預設值或 backfill)

  • 確認 item_id 語義粒度是否能唯一決定 pack type,再決定是否需要 item_secondary_type 欄位

相關概念

來源 Sessions

日期 Session 貢獻摘要

| 2026-03-31 | c903e4ed-15e4-4a39-b7b8-30b428e38075 | 確立 hot predicate(如 season_id)不應放 JSONB 的判斷標準,以 25M snapshot path 為具體門檻佐證 |


本概念頁面由 Semi-Brain Wiki 系統自動維護

最後更新: 2026-03-31