在 PHP 數據庫應用中五種常見的錯誤
阿恆
數據庫跟其他工具一樣,若果不正確地使用,很容易出現濫用的情況,Jack Herrington 在一篇文章中說,你可以在 PHP 應用程式中建立數據庫、存取資料,然後在其上編寫商業邏輯,達成這些目標很有方法,可惜很多人仍然把事情弄糟。在這篇文章中他闡述數據庫設計,和存取數據庫的 PHP 程式的五種常見毛病,還有如何避開這些毛病,文中並附有大量實例。這五種毛病是:
毛病一:直接存取 MySQL
一種在傳統 PHP 程式中常見的問題是使用 mysql_ 函數直接存取數據庫,作者建議使用 PEAR DB 模組或者 PHP Data Object (PDO),這些數據庫抽象曾使我們的系統可以隨時把數據庫轉換到 IBM DB2、PostgreSQL 等,此外也可以在 SQL 中使用 ? 操作元來使 SQL 語句更容易維護和更加安全。
毛病二:不使用 auto-increment 功能
MySQL 在建立資料表的時候容許我們定義 auto-increment 的欄位,可以自動產生唯一的數值作為資料表的主鍵,可惜仍然有大量的系統首先使用一句 SELECT 來決定當前 id 欄位的最大值,然後把 id 加一,並且把新資料插入資料表,對於負載重的伺服器有大量數據同時插入資料表,很容易產生 id 重複的情況,而且,這是極度低效的處理方法。解決方案便是使用 MySQL 的 auto-increment 功能,加入新資料後呼叫 MySQL 的 last_insert_id() 來讀取 auto-increment 欄位的最新數值。
毛病三:使用多個數據庫
我們偶然還會遇上一些應用程式把資料表分散到多個數據庫,在極端龐大的資料庫應用中這樣做或許是有道理的,但是在一般的應用環境我們卻不要自找麻煩,而且,我們無法編寫跨數據庫的 SQL 語句,這樣處理數據顯然違反了整個「關聯式數據庫」的設計理念,另外數據庫管理、備份等問題也足以令人頭疼。
毛病四:關聯不足
「關聯式數據庫」不像一般的編程語言具有陣列功能,它是透過資料表之間的關聯來實現 one-to-many 的對應,達到陣列的效果,一種常見的毛病是開發人員把資料欄位當作陣列看待,用逗號把資料分隔儲存在一個欄位中,這樣做效率既低、又難以維護,也沒有充分利用數據庫的特質。解決問題必須要重新設計數據庫的架構,使用更多的資料表,並且充分使用資料表間的關聯。
毛病五:n + 1 模式
實在有數不清的大型應用程式犯了這種毛病,首先 SELECT 一堆資料,例如用戶名單,然後再訪問資料庫逐一查詢用戶的詳細資料,這種做法稱為 n + 1 模式是因為我們總共訪問了資料庫 n + 1 次,其中 n 是用戶的人數,這是沒有效率的做法,若果我們希望系統跑得快,便要好好利用數據庫的功能,與及編寫聰明的 SQL 語句。
總結
數據庫是功能強大的工具,跟其他功能強大的工具一樣,不善用它的能力便會做成濫用,比不使用它還要糟糕,要識別和解決問題,最好是明白它背後所使用的技術,很多應用程式的開發人員把存取數據庫的工作封包在一個「物件」(object) 中,然後嚷著為何效能這麼低,他們不知道了解 SQL 的技術是優化數據庫操作的基礎。