資料庫反範式化設計:PHP程式設計中的運用

PHPz
發布: 2023-06-22 19:14:01
原創
918 人瀏覽過

隨著網路科技的快速發展,資料庫作為資料的儲存與管理中心,已成為現代資訊化時代不可或缺的一部分。在進行資料庫設計時,許多開發者會希望盡可能貼近資料庫規範化設計理論,使得資料表的結構合理、規範,方便維護與查詢。但是,在某些情況下,反範式設計(Denormalization)也是一種非常有用的技術,它透過冗餘資料和適當的資料組織來優化資料儲存和存取的效率。在PHP程式設計中,反範式設計可以大幅提高效能、降低資料庫機器負載,並且可以增強資料庫的可擴展性,縮短開發週期,本文將從反範式設計的原理、實現以及適用場景等方面,來講述PHP程式設計中如何運用反範式設計。

一、範式化設計與反範式化設計

在進行資料庫設計時,合理的範式化設計旨在使得資料表的結構更加規範、簡潔、準確,簡化操作、減小開發難度和資料冗餘度,提高資料的傳輸和安全性。資料庫範式化理論主要有1NF(第一範式)、2NF(第二範式)、3NF(第三範式)等幾個層次,約束了屬性的原子性、實體之間的關係依賴性和資料冗餘等方面。

反範式化設計則是相反的概念,它旨在透過增加某些資料冗餘度、優化查詢和加快速度來改善資料庫效能,主要是透過去規範化來實現,例如將欄位拆分到多個表中,以便在查詢時減少JOIN操作,或將冗餘資料儲存在多個表中,以便在更新時避免JOIN。但是,反範式化設計也有一定的局限性,在多數情況下,優秀的範式化設計仍然是首選。

二、反範式化設計的應用情境

反範式設計中應該遵循的原則是,在權衡設計時,需考慮到開發人員的需求和麵向使用者的需求。

  1. 查詢需求較高的場景

在需要頻繁查詢的情況下,使用反範式化設計可以最佳化查詢效率, 減少JOIN 運算和多層查詢等不必要的查詢,例如:使用者登入訊息,訂單詳情,等可先載入好緩存,在頁面展示時直接輸出。

  1. 資料庫寫入量高或訪問量大的情況

採用反範式設計可以減輕資料庫的壓力,將一些不需要變更的資料拆分到多張表上,避免寫入時產生鎖等情況,例如:商品價格,某些文字描述等可先緩存至某個地方,在真正寫入時再從快取中獲取。

  1. 部分資料需要及時更新/刪除的場景

採用反範式設計也可避免UPDATE和DELETE效率過低的情況。在資料量較大的情況下,UPDATE和DELETE操作會消耗大量的資源,採用反範式化設計可以將部分資料寫入多張表中,實現分散式處理和部分更新/刪除。

三、PHP程式如何應用反典範設計?

下面透過具體的PHP程式設計實例來展示如何運用反範式化設計:

  1. 前提假設:在訂單詳情頁面中需要展示訂單編號、產品ID、產品名稱、產品單價、產品數量、產品小計。存在訂單表和產品表兩個表,訂單表中存有訂單編號、產品ID、產品數量字段,產品表中存有產品ID、產品名稱、產品單價字段。
  2. 正常設計方案:透過聯結兩個表格查詢訂單及對應的產品資訊。如下所示:
SELECT order_no, product_id, product_name, product_price, product_qty, (product_price * product_qty) AS sub_total 
FROM order_tbl
LEFT OUTER JOIN product_tbl
ON order_tbl.product_id = product_tbl.product_id
WHERE order_no = '1001';
登入後複製
  1. 反範式化設計方案:將訂單表中的產品名稱、產品單價兩個欄位冗餘至訂單表中,以便在查詢時減少Join 操作。如下所示:
SELECT order_no, product_id, product_name, product_price, product_qty, (product_price * product_qty) AS sub_total 
FROM order_tbl
WHERE order_no = '1001';
登入後複製
  1. 實作步驟:

(1)建立兩個表格:order_tbl 和 product_tbl 。

CREATE TABLE `order_tbl` (
  `order_no` varchar(100) NOT NULL,
  `product_id` int(11) NOT NULL,
  `product_qty` int(11) NOT NULL,
  `product_name` varchar(100) DEFAULT NULL,
  `product_price` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `product_tbl` (
  `product_id` int(11) NOT NULL,
  `product_name` varchar(100) NOT NULL,
  `product_price` decimal(10,2) NOT NULL,
  PRIMARY KEY (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
登入後複製

(2)在訂單表 order_tbl 中冗餘兩個欄位:product_name 和 product_price。

ALTER TABLE `order_tbl` ADD COLUMN `product_name` VARCHAR(100) NOT NULL DEFAULT '';
ALTER TABLE `order_tbl` ADD COLUMN `product_price` DECIMAL(10,2) NOT NULL DEFAULT '0.00';
登入後複製

(3)在訂單寫入時,將資料寫入至order_tbl和快取表cache_tbl。

//写入订单表
$sql = "INSERT INTO order_tbl(order_no, product_id, product_qty, product_name, product_price) 
        VALUES ('$order_no', $product_id, $product_qty, '$product_name', $product_price)";

//写入缓存表
$sql_cache = "INSERT INTO cache_tbl(key_name, cache_value) 
              VALUES ('product_info_${product_id}','{"product_name":"${product_name}", "product_price":"${product_price}"}')";
登入後複製

(4)在訂單查詢時,先從快取表cache_tbl中取得產品名稱和價格,如果快取中不存在,則從產品表product_tbl中查詢並快取至cache_tbl。

$redis = new Redis(); 
$redis->connect('127.0.0.1', 6379);

$key_name = "product_info_${product_id}";
if ($redis->exists($key_name)) {
  $cache_data = json_decode($redis->get($key_name), true);
  $product_name = $cache_data['product_name'];
  $product_price = $cache_data['product_price'];
} else {
  $sql = "SELECT product_name, product_price FROM product_tbl WHERE product_id=$product_id";
  $result = mysqli_query($conn, $sql);
  $row = mysqli_fetch_array($result);
  $product_name = $row['product_name'];
  $product_price = $row['product_price'];
  $redis->set($key_name, json_encode(['product_name'=>$product_name, 'product_price'=>$product_price]));
}

$sql = "SELECT order_no, product_id, product_name, product_price, product_qty, (product_price * product_qty) AS sub_total 
        FROM order_tbl
        WHERE order_no = '1001'";
登入後複製

在這個例子中,我們使用Redis 做緩存,當查詢訂單詳情時,先從緩存中獲取產品名稱和價格,如果緩存中不存在,則從產品表中查詢並寫入緩存中。透過這個方法,我們避免了 JOIN 操作,大大提高了查詢效率和效能。

四、總結

反範式化設計既有優點又有缺點,合理的運用是關鍵。在進行資料庫設計時,應根據實際情況進行各種取捨,權衡利弊,靈活運用設計方法。在PHP程式設計中,透過反範式化設計來優化資料庫操作也是非常有用、實用的技術。我們可以透過增加冗餘資料、分散式處理、快取和索引策略等多種手段來提高資料庫效能和效率,提高系統的回應速度和使用者的滿意度。

以上是資料庫反範式化設計:PHP程式設計中的運用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板