一般在数据库中,我们保存的都只是 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

参考文档:

https://www.php.net/manual/zh/pdo.lobs.php

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

PDO操作大数据对象的更多相关文章

  1. Java数据库——处理大数据对象

    处理大数据对象 CLOB中可以存储海量文字 BLOB中可以存储海量二进制数据 如果程序中要想处理这样的大对象操作,则必须使用PreparedStatement完成,所有的内容要通过IO流的方式从大文本 ...

  2. 处理大数据对象clob数据和blob数据

    直接上下代码: package com.learn.jdbc.chap06; import java.io.File; import java.io.FileInputStream; import j ...

  3. array_chunk的用法和php操作大数据

    一.array_chunk() 函数 二.php操作大数据 1.在操作大数量数据与数据库交互时,比如插入大量数据,db就会报错,这时可以把原本的数据用array_chunk分隔成几个数组块,再循环插入 ...

  4. 怎么对MySQL数据库操作大数据?这里有思路

    最近学到一招关于使用java代码操作MySQL数据库,对大文本数据(LOB)进行CRUD的技巧,虽然向数据库很少向中存入大文本文件(一般都是存储在硬盘上),但是还是很有必要知道这一技巧的.下面我就来说 ...

  5. 吴裕雄--天生自然JAVA数据库编程:处理大数据对象

    import java.sql.Connection ; import java.sql.DriverManager ; import java.sql.SQLException ; import j ...

  6. 小书翻译完成,分享啦--《用Python操作大数据[MapReduceHadoop和Spark]》

    http://files.cnblogs.com/files/aguncn/%E7%94%A8Python%E6%93%8D%E4%BD%9C%E5%A4%A7%E6%95%B0%E6%8D%AE%5 ...

  7. 柯南君 :Oracle 分区技术 之 怎样支撑大数据操作?

    前段时间.看了罗女士( 资深技术顾问 - Oracle 中国 顾问咨询部)关于<大批量数据处理技术的演讲>视频.感觉受益良多,结合多年的知识积累,柯南君给大家分享一下: 交流内容: 一.O ...

  8. PHP 面试服务器优化和大数据

    服务器配置优化 系统参数调整 Linux 系统内核参数优化 vim /etc/sysctl.conf net.ipv4.ip_local_port_range = 1024 65535 # 用户端口范 ...

  9. 大数据系列4:Yarn以及MapReduce 2

    系列文章: 大数据系列:一文初识Hdfs 大数据系列2:Hdfs的读写操作 大数据谢列3:Hdfs的HA实现 通过前文,我们对Hdfs的已经有了一定的了解,本文将继续之前的内容,介绍Yarn与Yarn ...

随机推荐

  1. Recuva ——天下第一的删除恢复应用

    天下第一的删除恢复应用 下载地址    http://www.onlinedown.net/soft/66224.htm   实名diss那个垃圾  易得恢复  98一年,真是趁火打劫(跟个老鼠一样, ...

  2. CVE-2020-17523:Apache Shiro身份认证绕过漏洞分析

    0x01 Apache Shiro Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理. 0x02 漏洞简介 2021年2月1日,Apache Shiro官 ...

  3. Abp vNext 基础篇丨领域构建

    介绍 我们将通过例⼦介绍和解释⼀些显式规则.在实现领域驱动设计时,应该遵循这些规则并将其应⽤到解决⽅案中. 领域划分 首先我们先对比下Blog.Core和本次重构设计上的偏差,可以看到多了一个博客管理 ...

  4. Linux系统管理命令-systemctl 和 sshd 服务

    一系统服务管理命令systemctl 开启一个服务 : systemctl start sshd 关闭一个服务: systemctl stop sshd 查看一个服务的状态: systemctl st ...

  5. COM笔记-包容与聚合

    COM不支持实现继承的原因在于这种继承方式将使得一个对象的实现同另外一个对象的实现紧紧地关联起来.在这种情况下,当基类的实现被修改后,派生类将无法正常运行而必须被修改.这就是为什么一些用C++编写大型 ...

  6. Html 之自动高度 auto 和 100%高度

    HTML 高度 下面示例 设置为 Auto 和 100% <!DOCTYPE html> <html lang="en"> <head> < ...

  7. Python的dict

    dict把key和value关联起来,可以通过 key来查找 value. 花括号 {} 表示这是一个dict,然后按照 key: value, 写出来即可.最后一个 key: value 的逗号可以 ...

  8. ROS catkin_make error Could not find a package configuration file provided by "actionlib_msgs"

    在使用ROS catkin_make编译的时候,出现类似如下错误 CMake Error at /opt/ros/kinetic/share/catkin/cmake/catkinConfig.cma ...

  9. kubebuilder实战之八:知识点小记

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  10. 重启网络服务 network 出现问题

    2021-08-24 地址冲突了,因为想要设置成静态 ip 一直都不对,情急之下就将本地 ip 设置成了虚拟机的 ip,故出现此错误 后将地址改掉,重启网络服务就没有错误了 一开始我设置的虚拟网卡 n ...