mysql 中存储图片路径 啥类型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql 中存储图片路径 啥类型相关的知识,希望对你有一定的参考价值。

背景

mysql 一直以来都有 TEXT、BLOB 等类型用来存储图片、视频等大对象信息。比如一张图片,随便一张都 5M 以上。视频也是,随便一部视频就是 2G 以上。

假设用 MySQL 来存放电影视频等信息,一部是 2G,那么存储 1000 部就是 2TB,2TB 也就是 1000 条记录而已,但是对数据库性能来说,不仅仅是看记录数量,更主要的还得看占用磁盘空间大小。空间大了,所有以前的经验啥的都失效了。

所以一般来说存放这类信息,也就是存储他们的存放路径,至于文件本身存放在哪里,那这就不是数据库考虑的范畴了。数据库只关心怎么来的快,怎么来的小。


举例

虽然不推荐 MySQL 这样做,但是也得知道 MySQL 该怎么做才行,做到心里有数。比如下面一张微信图片,大概 5M 的样子。

root@ytt:/var/lib/mysql-files# ls -sihl 微信图片_20190711095019.jpg274501 5.4M -rw-r--r-- 1 root root 5.4M Jul 11 07:17 微信图片_20190711095019.jpg

拷贝 100 份这样的图片来测试

    root@ytt:/var/lib/mysql-files# for i in `seq 1 100`; do cp 微信图片_20190711095019.jpg "$i".jpg;done;

    root@ytt:/var/lib/mysql-files# ls

    100.jpg   17.jpg  25.jpg  33.jpg  41.jpg  4.jpg   58.jpg  66.jpg  74.jpg  82.jpg  90.jpg  99.jpg  f8.tsv

    10.jpg    18.jpg  26.jpg  34.jpg  42.jpg  50.jpg  59.jpg  67.jpg  75.jpg  83.jpg  91.jpg  9.jpg   微信图片_20190711095019.jpg

    1111.jpg  19.jpg  27.jpg  35.jpg  43.jpg  51.jpg  5.jpg   68.jpg  76.jpg  84.jpg  92.jpg  f1.tsv

    11.jpg    1.jpg   28.jpg  36.jpg  44.jpg  52.jpg  60.jpg  69.jpg  77.jpg  85.jpg  93.jpg  f2.tsv

    12.jpg    20.jpg  29.jpg  37.jpg  45.jpg  53.jpg  61.jpg  6.jpg   78.jpg  86.jpg  94.jpg  f3.tsv

    13.jpg    21.jpg  2.jpg   38.jpg  46.jpg  54.jpg  62.jpg  70.jpg  79.jpg  87.jpg  95.jpg  f4.tsv

    14.jpg    22.jpg  30.jpg  39.jpg  47.jpg  55.jpg  63.jpg  71.jpg  7.jpg   88.jpg  96.jpg  f5.tsv

    15.jpg    23.jpg  31.jpg  3.jpg   48.jpg  56.jpg  64.jpg  72.jpg  80.jpg  89.jpg  97.jpg  f6.tsv

    16.jpg    24.jpg  32.jpg  40.jpg  49.jpg  57.jpg  65.jpg  73.jpg  81.jpg  8.jpg   98.jpg  f7.tsv

    我们建三张表,分别用 LONGBLOB、LONGTEXT 和 VARCHAR 来存储这些图片信息

    mysql> show create table tt_image1G

    *************************** 1. row ***************************

    Table: tt_image1

    Create Table: CREATE TABLE `tt_image1` (

    `id` int(11) NOT NULL AUTO_INCREMENT,

    `image_file` longblob,

    PRIMARY KEY (`id`)

    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

    1 row in set (0.00 sec)

    mysql> show create table tt_image2G

    *************************** 1. row ***************************

    Table: tt_image2

    Create Table: CREATE TABLE `tt_image2` (

    `id` int(11) NOT NULL AUTO_INCREMENT,

    `image_file` longtext,

    PRIMARY KEY (`id`)

    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

    1 row in set (0.00 sec)

    mysql> show create table tt_image3G

    *************************** 1. row ***************************

    Table: tt_image3

    Create Table: CREATE TABLE `tt_image3` (

    `id` int(11) NOT NULL AUTO_INCREMENT,

    `image_file` varchar(100) DEFAULT NULL,

    PRIMARY KEY (`id`)

    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

    1 row in set (0.00 sec)

    我们来给三张表插入 100 张图片(插入前,建议把 max_allowed_packet 设置到最大)

    tt_image1

    root@ytt:/var/lib/mysql-files# for i in `seq 1 100`;

    do mysql -S /var/run/mysqld/mysqld.sock -e "insert into ytt.tt_image1(image_file)

    values (load_file('/var/lib/mysql-files/$i.jpg'))";done;

    tt_image2

    root@ytt:/var/lib/mysql-files# for i in `seq 1 100`;

    do mysql -S /var/run/mysqld/mysqld.sock -e "insert into ytt.tt_image2(image_file)

    values (hex(load_file('/var/lib/mysql-files/$i.jpg')))";done;

    tt_image3

    root@ytt:/var/lib/mysql-files# aa='begin;';for i in `seq 1 100`;

    do aa=$aa"insert into ytt.tt_image3(image_file) values

    ('/var/lib/mysql-files/$i.jpg');";

    done;aa=$aa'commit;';mysql -S /var/run/mysqld/mysqld.sock -e "`echo $aa`";

    检查下三张表记录数

    mysql> select 'tt_image1' as name ,count(*) from tt_image1 union allselect 'tt_image2',count(*) from tt_image2 union all select 'tt_image3', count(*) from tt_image3;+-----------+----------+| name      | count(*) |+-----------+----------+| tt_image1 |      100 || tt_image2 |      100 || tt_image3 |      100 |+-----------+----------+3 rows in set (0.00 sec)

    看下文件大小,可以看到实际大小排名,LONGTEXT 字段存储的最大,LONGBLOB 字段缩小到一半,最小的是存储图片路径的表 tt_image3。所以这里从存储空间来看,存放路径最占优势。

    root@ytt:/var/lib/mysql/ytt# ls -silhS tt_image*274603 1.1G -rw-r----- 1 mysql mysql 1.1G Jul 11 07:27 tt_image2.ibd274602 545M -rw-r----- 1 mysql mysql 544M Jul 11 07:26 tt_image1.ibd274605  80K -rw-r----- 1 mysql mysql 112K Jul 11 07:27 tt_image3.ibd

    那么怎么把图片取出来呢?

    tt_image3 肯定是最容易的

    mysql> select * from tt_image3;+----+----------------------------+| id | image_file                 |+----+----------------------------+|  1 | /var/lib/mysql-files/1.jpg |+----+----------------------------+...100 rows in set (0.00 sec)

    tt_image1 直接导出来二进制文件即可,下面我写了个存储过程,导出所有图片。

    mysql> DELIMITER $$mysql> USE `ytt`$$mysql> DROP PROCEDURE IF EXISTS `sp_get_image`$$mysql> CREATE DEFINER=`ytt`@`localhost` PROCEDURE `sp_get_image`()mysql> BEGIN      DECLARE i,cnt INT DEFAULT 0;      SELECT COUNT(*) FROM tt_image1 WHERE 1 INTO cnt;      WHILE i < cnt DO        SET @stmt = CONCAT('select image_file from tt_image1  limit ',i,',1 into dumpfile ''/var/lib/mysql-files/image',i,'.jpg''');        PREPARE s1 FROM @stmt;        EXECUTE s1;        DROP PREPARE s1;      SET i = i + 1;      END WHILE;      END$$mysql> DELIMITER ;mysql> call sp_get_image;

    tt_image2 类似,把 select 语句里 image_file 变为 unhex(image_file) 即可。

    总结

    这里我举了个用 MySQL 来存放图片的例子,总的来说有以下三点:

    占用磁盘空间大(这样会带来各种各样的功能与性能问题,比如备份,写入,读取操作等)

    使用不易

    还是推荐用文件路径来代替实际的文件内容存放

参考技术A varchar类型追问

在网页中读取为什么不显示图片

追答

要看你程序语句如何写的,一般就是
" />

关于MYSQL 时间类型存储在数据库里是啥类型

参考技术A Mysql中经常用来存储日期的数据类型有三种:Date、Datetime、Timestamp。

Date数据类型:用来存储没有时间的日期。Mysql获取和显示这个类型的格式为“YYYY-MM-DD”。支持的时间范围为“1000-00-00”到“9999-12-31”。

Datetime类型:存储既有日期又有时间的数据。存储和显示的格式为 “YYYY-MM-DD HH:MM:SS”。支持的时间范围是“1000-00-00 00:00:00”到“9999-12-31 23:59:59”。

Timestamp类型:也是存储既有日期又有时间的数据。存储和显示的格式跟Datetime一样。支持的时间范围是“1970-01-01 00:00:01”到“2038-01-19 03:14:07”。

所有不符合上面所述格式的数据都会被转换为相应类型的0值。(0000-00-00或者0000-00-00 00:00:00)
参考技术B

MySQL 数据类型细分下来,大概有以下几类:

    数值,典型代表为 tinyint,int,bigint

    浮点/定点,典型代表为 float,double,decimal 以及相关的同义词

    字符串,典型代表为 char,varchar

    时间日期,典型代表为 date,datetime,time,timestamp

    二进制,典型代表为 binary,varbinary

    位类型

    枚举类型

    集合类型

    大对象,比如 text,blob

    json 文档类型

    一、数值类型(不是数据类型,别看错了)如果用来存放整数,根据范围的不同,选择不同的类型。


    以上是几个整数选型的例子。整数的应用范围最广泛,可以用来存储数字,也可以用来存储时间戳,还可以用来存储其他类型转换为数字后的编码,如 IPv4 等。示例 1用 int32 来存放 IPv4 地址,比单纯用字符串节省空间。表 x1,字段 ipaddr,利用函数 inet_aton,检索的话用函数 inet_ntoa。

    查看磁盘空间占用,t3 占用最大,t1 占用最小。所以说如果整数存储范围有固定上限,并且未来也没有必要扩容的话,建议选择最小的类型,当然了对其他类型也适用。root@ytt-pc:/var/lib/mysql/3305/ytt# ls -sihl总用量 3.0G3541825 861M -rw-r----- 1 mysql mysql 860M 12月 10 11:36 t1.ibd3541820 989M -rw-r----- 1 mysql mysql 988M 12月 10 11:38 t2.ibd3541823 1.2G -rw-r----- 1 mysql mysql 1.2G 12月 10 11:39 t3.ibd

    二、浮点数 / 定点数先说 浮点数,float 和 double 都代表浮点数,区别简单记就是 float 默认占 4 Byte。float(p) 中的 p 代表整数位最小精度。如果 p > 24 则直接转换为 double,占 8 Byte。p 最大值为 53,但最大值存在计算不精确的问题。再说 定点数,包括 decimal 以及同义词 numeric,定点数的整数位和小数位分别存储,有效精度最大不能超过 65。所以区别于 float 的在于精确存储,必须需要精确存储或者精确计算的最好定义为 decimal 即可。示例 3创建一张表 y1,分别给字段 f1,f2,f3 不同的类型。mysql-(ytt/3305)->create table y1(f1 float,f2 double,f3 decimal(10,2));Query OK, 0 rows affected (0.03 sec)


    三、字符类型字符类型和整形一样,用途也很广。用来存储字符、字符串、MySQL 所有未知的类型。可以简单说是万能类型!


    char(10) 代表最大支持 10 个字符存储,varhar(10) 虽然和 char(10) 可存储的字符数一样多,不同的是 varchar 类型存储的是实际大小,char 存储的理论固定大小。具体的字节数和字符集相关。示例 4例如下面表 t4 ,两个字段 c1,c2,分别为 char 和 varchar。mysql-(ytt/3305)->create table t4 (c1 char(20),c2 varchar(20));Query OK, 0 rows affected (0.02 sec)


    所以在 char 和 varchar 选型上,要注意看是否合适的取值范围。比如固定长度的值,肯定要选择 char;不确定的值,则选择 varchar。


    四、日期类型日期类型包含了 date,time,datetime,timestamp,以及 year。year 占 1 Byte,date 占 3 Byte。 


    time,timestamp,datetime 在不包含小数位时分别占用 3 Byte,4 Byte,8 Byte;小数位部分另外计算磁盘占用,见下面表格。

    请点击输入图片描述

    请点击输入图片描述

    请点击输入图片描述

    注意:timestamp 代表的时间戳是一个 int32 存储的整数,取值范围为 '1970-01-01 00:00:01.000000' 到 '2038-01-19 03:14:07.999999';datetime 取值范围为 '1000-01-01 00:00:00.000000' 到 '9999-12-31 23:59:59.999999'。 

    综上所述,日期这块类型的选择遵循以下原则:

    1. 如果时间有可能超过时间戳范围,优先选择 datetime。2. 如果需要单独获取年份值,比如按照年来分区,按照年来检索等,最好在表中添加一个 year 类型来参与。3. 如果需要单独获取日期或者时间,最好是单独存放,而不是简单的用 datetime 或者 timestamp。后面检索时,再加函数过滤,以免后期增加 SQL 编写带来额外消耗。

    4. 如果有保存毫秒类似的需求,最好是用时间类型自己的特性,不要直接用字符类型来代替。MySQL 内部的类型转换对资源额外的消耗也是需要考虑的。

    示例 5

    建立表 t5,对这些可能需要的字段全部分离开,这样以后写 SQL 语句的时候就很容易了。

    当然了,这种情形占用额外的磁盘空间。如果想在易用性与空间占用量大这两点来折中,可以用 MySQL 的虚拟列来实时计算。比如假设 c5 字段不存在,想要得到 c5 的结果。mysql-(ytt/3305)->alter table t5 drop c5, add c5 year generated always as (year(c1)) virtual;Query OK, 1 row affected (2.46 sec)Records: 1  Duplicates: 0  Warnings: 0



    五、二进制类型

    binary 和 varbinary 对应了 char 和 varchar 的二进制存储,相关的特性都一样。不同的有以下几点:

    binary(10)/varbinary(10) 代表的不是字符个数,而是字节数。

    行结束符不一样。char 的行结束符是 \\0,binary 的行结束符是 0x00。

    由于是二进制存储,所以字符编码以及排序规则这类就直接无效了。

    示例 6

    来看这个 binary 存取的简单示例,还是之前的变量 @a。

    切记!这里要提前计算好 @a 占用的字节数,以防存储溢出。


    六、位类型

    bit 为 MySQL 里存储比特位的类型,最大支持 64 比特位, 直接以二进制方式存储,一般用来存储状态类的信息。比如,性别,真假等。具有以下特性:

    1. 对于 bit(8) 如果单纯存放 1 位,左边以 0 填充 00000001。2. 查询时可以直接十进制来过滤数据。3. 如果此字段加上索引,MySQL 不会自己做类型转换,只能用二进制来过滤。

    示例 7

    创建表 c1, 字段性别定义一个比特位。mysql-(ytt/3305)->create table c1(gender bit(1));Query OK, 0 rows affected (0.02 sec)



    mysql-(ytt/3305)->select cast(gender as unsigned)  'f1' from c1;+------+| f1   |+------+|    0 ||    1 |+------+2 rows in set (0.00 sec)


    过滤数据也一样,二进制或者直接十进制都行。mysql-(ytt/3305)->select conv(gender,16,10) as gender \\   -> from c1 where gender = b'1'; +--------+| gender |+--------+| 1      |+--------+1 row in set (0.00 sec)    mysql-(ytt/3305)->select conv(gender,16,10) as gender \\    -> from c1 where gender = '1';+--------+| gender |+--------+| 1      |+--------+1 row in set (0.00 sec)


    其实这样的场景,也可以定义为 char(0),这也是类似于 bit 非常优化的一种用法。

    mysql-(ytt/3305)->create table c2(gender char(0));Query OK, 0 rows affected (0.03 sec)


    那现在我给表 c1 简单的造点测试数据。

    mysql-(ytt/3305)->select count(*) from c1;+----------+| count(*) |+----------+| 33554432 |+----------+1 row in set (1.37 sec)


    把 c1 的数据全部插入 c2。

    mysql-(ytt/3305)->insert into c2 select if(gender = 0,'',null) from c1;Query OK, 33554432 rows affected (2 min 18.80 sec)Records: 33554432  Duplicates: 0  Warnings: 0


    两张表的磁盘占用差不多。root@ytt-pc:/var/lib/mysql/3305/ytt# ls -sihl总用量 1.9G4085684 933M -rw-r----- 1 mysql mysql 932M 12月 11 10:16 c1.ibd4082686 917M -rw-r----- 1 mysql mysql 916M 12月 11 10:22 c2.ibd


    检索方式稍微有些不同,不过效率也差不多。所以说,字符类型不愧为万能类型。


    七、枚举类型

    枚举类型,也即 enum。适合提前规划好了所有已经知道的值,且未来最好不要加新值的情形。枚举类型有以下特性:

    1. 最大占用 2 Byte。2. 最大支持 65535 个不同元素。3. MySQL 后台存储以下标的方式,也就是 tinyint 或者 smallint 的方式,下标从 1 开始。4. 排序时按照下标排序,而不是按照里面元素的数据类型。所以这点要格外注意。

    示例 8

    创建表 t7。mysql-(ytt/3305)->create table t7(c1 enum('mysql','oracle','dble','postgresql','mongodb','redis','db2','sql server'));Query OK, 0 rows affected (0.03 sec)



    八、集合类型

    集合类型 SET 和枚举类似,也是得提前知道有多少个元素。SET 有以下特点:

    1. 最大占用 8 Byte,int64。2. 内部以二进制位的方式存储,对应的下标如果以十进制来看,就分别为 1,2,4,8,...,pow(2,63)。3. 最大支持 64 个不同的元素,重复元素的插入,取出来直接去重。4. 元素之间可以组合插入,比如下标为 1 和 2 的可以一起插入,直接插入 3 即可。

    示例 9

    定义表 c7 字段 c1 为 set 类型,包含了 8 个值,也就是下表最大为 pow(2,7)。

    mysql-(ytt/3305)->create table c7(c1 set('mysql','oracle','dble','postgresql','mongodb','redis','db2','sql server'));Query OK, 0 rows affected (0.02 sec)


    插入 1 到 128 的所有组合。

    mysql-(ytt/3305)->INSERT INTO c7WITH RECURSIVE ytt_number (cnt) AS (        SELECT 1 AS cnt        UNION ALL        SELECT cnt + 1        FROM ytt_number        WHERE cnt < pow(2, 7)    )SELECT *FROM ytt_number;Query OK, 128 rows affected (0.01 sec)Records: 128  Duplicates: 0  Warnings: 0

    九、数据类型在存储函数中的用法

    函数里除了显式声明的变量外,默认 session 变量的数据类型很弱,随着给定值的不同随意转换。

    示例 10

    定义一个函数,返回两个给定参数的乘积。定义里有两个变量,一个是 v_tmp 显式定义为 int64,另外一个 @vresult 随着给定值的类型随意变换类型。


    简单调用下。

    mysql-(ytt/3305)->select ytt_sample_data_type(1111,222) 'result';+--------------------------+| result                   |+--------------------------+| The result is: '246642'. |+--------------------------+1 row in set (0.00 sec)


    总结

    本篇把 MySQL 基本的数据类型做了简单的介绍,并且用了一些容易理解的示例来梳理这些类型。我们在实际场景中,建议选择适合最合适的类型,不建议所有数据类型简单的最大化原则。比如能用 varchar(100),不用 varchar(1000)。

以上是关于mysql 中存储图片路径 啥类型的主要内容,如果未能解决你的问题,请参考以下文章

数据库中图片存储为BLOB类型,如何取出转换

mysql数据库可以存图片路径?

Android获取数据库图片uri路径并用imageView显示

SQL数据库中提取图片路径

在asp.net中,加载图片的相对路径和绝对路径分别用啥

数据库存储图片路径并显示图片