許多企業在規劃客製化系統時,會把預算與時間集中在功能開發、UI 設計與第三方整合,但真正會決定系統 3 年後還能不能擴展、是否經得起資料量成長、能不能撐起報表與 AI 分析的,往往是上線前 2 週才被「順便決定」的資料庫設計。
資料庫設計是少數一旦上線就難以全面翻新的環節:欄位定義錯了、外鍵漏設了、索引沒建好,等到系統累積幾百萬筆資料後再回頭調整,往往要付出停機、重寫程式、重建索引等高昂代價。本文整理山葵組多年協助企業建置客製化系統的經驗,拆解 8 個資料庫設計階段必須做對的關鍵決策。
2026 年的台灣企業專案中,90% 以上的核心業務資料仍應以關聯式資料庫(PostgreSQL、MySQL)為主體。原因很簡單:客製化系統往往涉及訂單、會員、權限、金流、發票等高度結構化、強一致性需求的資料,這些場景恰好是 SQL 資料庫的強項。
NoSQL(MongoDB、DynamoDB)適合用於日誌、行為追蹤、IoT 大量寫入、文件型內容、即時聊天訊息等彈性 Schema 場景。建議採用「以 SQL 為主、NoSQL 為輔」的混合架構:核心交易資料放 PostgreSQL,行為紀錄、聊天訊息、AI 對話歷史等彈性資料放 MongoDB 或 Elasticsearch。
新手開發者常見的兩種極端:一是過度正規化,把所有欄位拆到第三正規化(3NF),結果一次查詢要 join 6 個表;二是完全不正規化,所有資料塞在同一張寬表,造成資料重複與一致性災難。
實務建議:核心主表(會員、訂單、商品)採用 3NF 設計,避免資料異常;報表查詢密集、效能要求高的場景,採用適度反正規化(denormalization),例如在訂單表冗餘儲存「下單時的會員姓名」,避免會員改名後歷史訂單顯示變動。客戶管理(CRM)、ERP 報表表這類場景,可以另建專屬的彙總表或 Materialized View。
索引是效能調校最容易被誤用的工具。常見錯誤包括:把每個欄位都加上單欄索引,導致寫入效能崩潰;對低基數欄位(如性別、狀態)建索引,幾乎沒有效果;不懂複合索引的最左前綴原則,建了卻用不上。
正確做法:先用 EXPLAIN 分析高頻查詢,針對 WHERE、JOIN、ORDER BY 涉及的欄位組合建立複合索引;對高基數欄位(如 email、phone)建立唯一索引;對只查不寫的報表場景,使用覆蓋索引(covering index)避免回表;定期檢視 pg_stat_user_indexes 或 sys.dm_db_index_usage_stats,刪除從未被使用的索引。
過去 10 年大多採用自增整數(auto increment)作為主鍵,優點是儲存效率高、索引緊湊、可讀性好。但在 2026 年的多服務、跨資料庫、需要前端產生 ID(離線優先 APP)的場景下,UUID(特別是 UUIDv7,含時間排序)逐漸成為首選。
實務建議:單一資料庫、單一服務、且不需要分散式 ID 生成的傳統系統,使用 BIGINT 自增主鍵即可;微服務、需要合併資料、有離線同步需求、或需避免猜測 ID 漏洞的系統,使用 UUIDv7。注意:UUID 比 BIGINT 大 4 倍,會增加索引與儲存成本,必要時可保留自增 ID 作內部主鍵、另開 public_id 欄位儲存 UUID 對外。
很多 Bug 其實源自欄位設計階段。例如:金額用 FLOAT 而非 DECIMAL,導致千分之一元的累積誤差;身分證、手機用 INT 儲存,丟失前導零;狀態欄位沒有 ENUM 或 CHECK 約束,導致髒資料混入。
實務建議:金額一律用 DECIMAL(10,2) 或 DECIMAL(14,4);可變長文字用 VARCHAR(n) 並設定合理上限,避免無上限的 TEXT 被濫用;列舉值用 ENUM 或外鍵到字典表;NOT NULL 應該是預設值而非例外,能用 DEFAULT 補預設值的就不要允許 NULL;外鍵約束務必加上,並選擇正確的 ON DELETE 策略(RESTRICT、CASCADE、SET NULL)。
每張表都應該至少有 created_at 與 updated_at,並建立 trigger 或在 ORM 層自動更新;需要追蹤刪除歷史的表(會員、訂單、合約)採用軟刪除(deleted_at),但要注意所有查詢都要加 WHERE deleted_at IS NULL 過濾。
對於金流、稽核、合約等高敏感資料,建議建立完整的 audit log 機制:以 trigger 或 application 層自動把每次寫入記錄到專屬 audit 表,欄位包含操作人員、操作時間、變更前後值、IP、來源等。GDPR、個資法稽核時這些 log 是企業免於高額罰款的關鍵證據。
手動跑 SQL 改 Schema 是中型專案最大的災難來源。應該採用 Migration 工具(Laravel Migration、Flyway、Liquibase、Prisma Migrate)把每一次 Schema 變更都寫成版本化的程式檔,與程式碼一起進 Git。
大表變更(加欄位、改型別、加索引)必須採用線上 DDL 工具或分階段策略,避免長時間鎖表:先 ADD COLUMN(NULL 允許)、再批次回填、最後加 NOT NULL 與索引。MySQL 可用 pt-online-schema-change、gh-ost;PostgreSQL 可用 CREATE INDEX CONCURRENTLY。每一次 Migration 必須附帶 rollback 腳本,避免出包時無法回滾。
客製化系統上線後,最怕的不是寫程式的 bug,而是資料庫整個壞掉、誤刪除、或被勒索軟體加密。企業必須在簽約階段就釐清兩個指標:RPO(Recovery Point Objective,最多能容忍丟失多少時間的資料)與 RTO(Recovery Time Objective,多久必須恢復服務)。
實務建議:日常採用 PITR(Point-In-Time Recovery)+ 每日全備份 + 異地備份的三層策略;金流、訂單等關鍵交易系統採用主從同步(Streaming Replication 或 RDS Multi-AZ),確保主機房故障時可在分鐘級切換;每季實際演練一次「從零還原」流程,確保備份不是備而不能用。
從山葵組過去的案例經驗來看,在系統開發初期多花 1~2 週把資料庫設計做對,往往可以省下後續 3~6 個月的重構成本。資料庫一旦設計完成、資料開始累積,越往後改動的代價越高。
如果您的企業正在規劃客製化系統,或對現有系統的資料庫架構有疑慮,歡迎與山葵組聯繫,我們提供從 SA 訪談、Schema 設計、效能稽核到資料庫遷移的完整顧問與開發服務,協助企業打造可長期維運的系統地基。