首頁  >  文章  >  資料庫  >  PDO如何操作大數據對象

PDO如何操作大數據對象

醉折花枝作酒筹
醉折花枝作酒筹轉載
2021-06-10 17:06:072923瀏覽

本篇文章給大家詳細介紹PDO操作大數據物件的方法。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

PDO如何操作大數據對象

一般在資料庫中,我們保存的都只是int 、 varchar 類型的數據,一是因為現代的關係型資料庫對於這些內容會有很多的最佳化,二是大部分的索引也無法施加在內容過多的欄位上,比如說text 類型的欄位就很不適合建立索引。所以,我們在使用資料庫時,很少會儲存很大的內容欄位給資料庫。但是,MySQL 其實也為我們準備了這種類型的存儲,只是我們平常用得不多而已。今天我們就來學習了解使用 PDO 如何操作 MySQL 中的大資料物件。

什麼是大數據物件

“大”通常意味著“大約4kb 或以上”,儘管某些資料庫在資料達到“大”之前可以輕鬆地處理多達32kb 的資料。大物件本質上可能是文字或二進位形式的,我們在 PDOStatement::bindParam() 或 PDOStatement::bindColumn() 呼叫中使用 PDO::PARAM_LOB 類型碼可以讓 PDO 使用大資料類型。 PDO::PARAM_LOB 告訴 PDO 作為流來映射數據,以便能使用 PHP Streams API 來操作。

對於 MySQL 來說,將欄位類型設為 blob 即是大物件格式的欄位。而在 bindParam() 或 bindColumn() 時,指定欄位的參數為 PDO::PARAM_LOB 類型,就可以直接以句柄形式取得這個物件裡面的內容,就像 fopen() 一樣地繼續對它進行操作。

CREATE TABLE `zy_blob` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `attach` longblob,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

這是我們測試用的一個資料表,將 attach 欄位設定為了 longblob 類型,也就是比較大的 blob 類型,這樣我們就可以儲存更多地資訊。畢竟現在的圖片或文件隨便就是輕鬆地幾m或幾十m起步的,我們直接使用最大的 blob 類型來進行簡單地測試。 tinyblob 的大小為 255 位元組,blob 類型的大小為 65k ,mediumblob 為 16M ,longblob 為 4G 。

直接操作大數據物件會怎麼樣?

我們先來簡單地直接操作大數據對象,看看是什麼樣的結果。

$stmt = $pdo->prepare("insert into zy_blob (attach) values (?)");
$fp = fopen('4960364865db53dcb33bcf.rar', 'rb');
$stmt->execute([$fp]);

$stmt = $pdo->query("select attach from zy_blob where id=1");
$file = $stmt->fetch(PDO::FETCH_ASSOC);
print_r($file); 
// Array
// (
//     [attach] => Resource id #6
// )

在這段程式碼中,我們沒有綁定字段,然後直接將 fopen() 開啟的檔案儲存到 blob 字段中。可以看出,在資料庫中,blob 相關的欄位只是儲存了 Resource id #6 這樣的字串。也就是說,在不做任何處理的情況下,$fp 句柄被強制轉換成了字串類型,而句柄類型被強轉的結果就是只會輸出一個資源ID,而blob 也只是和字元類型的字段一樣記錄了這個字串而已。

正確的姿勢

接下來我們來看看正確的姿勢,也就是透過 bindParam() 來插入數據,透過 bindColumn() 來讀取資料。

$stmt = $pdo->prepare("insert into zy_blob (attach) values (?)");

$fp = fopen('4960364865db53dcb33bcf.rar', 'rb');

$stmt->bindParam(1, $fp, PDO::PARAM_LOB); // 绑定参数类型为 PDO::PARAM_LOB
$stmt->execute();

$stmt = $pdo->prepare("select attach from zy_blob where id=2");
// // $file = $stmt->fetch(PDO::FETCH_ASSOC);
// // print_r($file); // 空的
$stmt->execute();
$stmt->bindColumn(1, $file, PDO::PARAM_LOB); // 绑定一列到一个 PHP 变量
$stmt->fetch(PDO::FETCH_BOUND); // 指定获取方式,返回 TRUE 且将结果集中的列值分配给通过 PDOStatement::bindParam() 或 PDOStatement::bindColumn() 方法绑定的 PHP 变量
print_r($file); // 二进制乱码内容
$fp = fopen('a.rar', 'wb');
fwrite($fp, $file);

首先,我們透過 bindParam() 綁定數據,並指定 PDO::PARAM_LOB 類型之後,就正常地向資料庫插入了檔案的句柄二進位內容。接著,我們使用 bindColumn() 並且也指定 PDO::PARAM_LOB 類型來獲得查詢出來的資料。直接列印查詢出來的欄位訊息,就可以看到它是二進位的類型內容。最後,我們將這個二進位內容保存成另一個名稱的檔案。

大家可以取代上面的檔案內容,然後執行程式碼來看看最後產生的檔案是不是跟原來的檔案一樣的。我這裡使用的是一個壓縮包文件,最後生成的 a.rar 文件和原始文件大小以及解壓縮後的內容都是完全一致的。

總結

大資料物件操作的究竟是什麼呢?其實就是我們平常要保存的大文件。我們將這些檔案以二進位流的方式讀取到程式後,再將它們保存在資料庫的欄位中。想想我們平常開發用到的最多的圖片保存就可以用這個來做。但是,這裡可以劃重點了,我們更加推薦的還是將文件直接保存在文件目錄中,而資料庫中只保存它們的路徑就可以了。資料庫資源是寶貴的,表越大越不利於優化,而且資料庫本身還有快取機制,浪費它的資源來保存這種大型的文件其實是得不償失的。當然,如果有某些特殊的需要,例如一些私密文件不想直接在硬碟文件目錄中保存,或者做為臨時的跨伺服器儲存方案都是可以的。

在现代开发中,相信你的公司也不会吝啬到不去买一个云存储(七牛、upyun、阿里云OSS)。它们不仅仅是能够做为一个存储器、网盘,而是有更多的功能,比如图片的裁剪、水印,赠送的 CDN 、带宽 、 流量之类的,总之,现代的存储大家还是尽量上云吧,即使是个人开发,也有不少厂商会提供小流量小数据量情况下的免费使用,这个都比我们自己来要方便很多。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/PDO%E6%93%8D%E4%BD%9C%E5%A4%A7%E6%95%B0%E6%8D%AE%E5%AF%B9%E8%B1%A1.php

相关推荐:《mysql教程

以上是PDO如何操作大數據對象的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除