分析大文本与图像数据在数据库内部的存储原理。

分析大文本与图像数据在数据库内部的存储原理。,第1张

图像数据在数据库内部的存储原理:

XML 是文本型的数据交换结构,对于字符类型的文本交换非常的方便,实际工作中我们往往需要通过 XML 将二进制格式的图形图像信息数据进行数据交换。本文从介绍 BASE64 编码的原理入手,通过采用 C 语言编写 DB2 的嵌入存储过程,实现了在数据库内存中将文本格式的文件到二进制 BLOB 字段之间的转换,并且就性能优化等提出若干建议,该设计思路和程序可以广泛的应用到图像图形数据在 XML 的存储和转换。

--------------------------------------------------------------------------------

回页首

XML 存储图形图像的基本原理

XML 作为一种非常广泛的数据交换的载体被广泛的应用到了各行各业的数据交换中。对于图形图像数据的转换,需要采用 Base64 编码将二进制格式的图形图像信息转换成文本格式再进行传输。

Base64 编码转换的思想是通过 64 个 ASCII 字符码对二进制数据进行重新编码组合,即将需要转换的数据每三个字节(24 位)为一组,再将这 24 位数据按每组 6 位进行重新划分,在每组的最高 2 位填充 0 最终成一个完整的 8 位字节。如果所要编码的数据的字节数不是 3 的整数倍,需要在最后一组数据填充 1 到 2 个字节的 0 字节。例如:我们对 ABC 进行 BASE64 的编码,ABC 的编码值:A(65), B(66), C(67)。再取二进制 A(01000001)B(01000010)C(01000011)连接起来构成 010000010100001001000011,然后按 6 位为单位分成 4 个数据块并在最高位填充两个 0 后形成 4 个字节的编码后的值(00010000)(00010100)(00001001)(00000011)。再将 4 个字节的数据转换成十进制数为(16)(20)(19)(3)。最后根据 BASE64 给出的 64 个基本字符表,查出对应的 ASCII 码字符(Q)(U)(J)(D)。这里的值实际就是数据在字符表中的索引。

BASE64 字符表:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789。

某项目的数据交换采用 XML 的为介质,XML 的结构包括个人基本信息:姓名、性别、相片等信息,其中相片信息是采用经过 BASE64 函数转换后的文本型数据,图像图形信息通过 BASE64 进行数据转换后,形成文本格式的数据类型,再将相应的数据存放到 XML 中,最终形成可供交换的文本型的 XML 数据结构。

XML 的数据结构如下所示:

<xml version=”10” encoding=”UTF-8” >

<HeadInfo>

<TotalNum>10<TotalNum>

<TransDate>2007-10-18</TransDate>

</HeadInfo>

<Data>

<Name> 张三 </Name>

<Sex> 男 </Sex>

<Photo>/9j/4AAQSkZJRgABAQAAAQABAAD</Photo>

<Data>

--------------------------------------------------------------------------------

回页首

相片数据在 DB2 嵌入式 C 程序的实现方法

该项目要求能够在 DB2 数据库中将相片数据存储为二进制 BLOB 格式。我们采用 DATASTAGE 进行 XML 数据加载,将 XML 中的姓名、性别等基本数据项加载到相应的字段,其中文本型的相片数据则加载到 CLOB 字段中,再按照 BASE64 的编码规则进行逆向转码,整个数据流程如下图所示:

图 1 相片存储流程图

用户的相片每天的更新数据为 30 万条,而且每个相片的平均大于 32KB,为了获得最佳的数据库性能,选择采用 C 存储过程的方式开发了 BASE64 的转换函数。每次函数读取存储在 CLOB 字段的文本格式数据全部存储到内存中,并且通过 decode 函数在内存中进行转码,转码后再存入数据库中。

程序的清单 1 是逐行读取 CLOB 字段,并且调用 decode 函数进行转码;程序的清单 2 是 decode 函数的关键性代码。完整的程序见源代码下载部分。

清单 1 读入 CLOB,写入 BLOB 字段

EXEC SQL BEGIN DECLARE SECTION;

SQL TYPE IS CLOB(100 K) clobResume; //CLOB 结构体变量

SQL TYPE IS BLOB(100 K) blobResume; //BLOB 结构体变量

sqlint16 bobind;

sqlint16 lobind;

sqlint16 cobind;

sqlint32 idValue;

EXEC SQL END DECLARE SECTION;

int clob2bin(void)

{

// 声明 SQLCA 结构

struct sqlca sqlca;

int charNb;

int lineNb;

long n;

n=0;

// 定义数据库游标

EXEC SQL DECLARE c1 CURSOR WITH HOLD FOR

SELECT czrkxp_a

FROM CZRK_blob for update;

EXEC SQL OPEN c1;

// 活动 CLOB 字段的信息,已经 CLOB 字段的大小

EXEC SQL FETCH c1 INTO :clobResume:cobind;

// 循环读取 CLOB 字段,并且调用 DECODE 转码函数

while (sqlcasqlcode != 100)

{

if (cobind < 0)

{

printf(“ NULL LOB indicated\n”);

}

else

{

n++;

decode(); // 文本格式到二进制流的转码函数

printf(“\nCurrent Row =%ld”,n);

// 数据写入 BLOB 字段

EXEC SQL update czrk_blob set czrkxp_blob = :blobResume

where current of c1; ;

// 提交事务

EXEC SQL COMMIT;

}

EXEC SQL FETCH c1 INTO :clobResume:cobind ;

}

// 关闭游标

EXEC SQL CLOSE c1;

EXEC SQL COMMIT;

return 0;

}

清单 2 文本文件到二进制文件的转换

void decode( void )

{

unsigned char in[4], out[3], v;

int I, len;

long j,k;

j = -1;

k=0;

// 将读入 CLOB 结构体变量的数据进行转换

while( j < clobResumelength){

for( len = 0, I = 0; I < 4 && ( j < clobResumelength ); i++ ) {

v = 0;

while((j < clobResumelength) && v == 0 ) {

j++;

v = (unsigned char) clobResumedata[j];

v = (unsigned char) ((v < 43 || v > 122) 0 : cd64[ v – 43 ]);

if( v ) {

v = (unsigned char) ((v == ‘$’) 0 : v – 61);

}

}

if( j < clobResumelength ) {

len++;

if( v ) {

in[ I ] = (unsigned char) (v – 1);

}

}

else {

in[i] = 0;

}

}

if( len ) {

decodeblock( in, out );

// 写入到 BLOB 结构体变量中

for( I = 0; I < len – 1; i++ ) {

blobResumedata[k] = out[i];

k++;

}

}

}

blobResumelength= k;

}

--------------------------------------------------------------------------------

回页首

数据的转换效率和优化建议

在 IBM P570 数据库服务器上运行,该程序的运行效率非常高,先后进行了几个数量级的测试,最终平均测试的转换效率为:每 1 万笔数据记录,转换的效率 55 秒,即 182 条 / 秒。值得注意的是,整个转换过程占用 CPU 的量并不特别大,主要的性能瓶颈在磁盘阵列中。

以后可以进一步在以下方面进行调优,确保程序转换的效率更高:

1)采用多进程调用的方式,以获得更高的并发数量;

2)采用每 10 次或者 100 次提交事务的方式,减少访问磁盘的次数;

3)将 CLOB 和 BLOB 分别放置在不同的表空间上,并且将表空间分布在在多个磁盘上,获得最佳的磁盘访问速度。

你说的大型网站,应该指的只是这个网站的 数量特别多, 但是一般是不存在数据库的,因为那样读写起来很慢, 大多数是 直接把的 路径存下来, 据我个人了解, 千万数量级别的,如果只是查询 的位置, 而且反复查询的, 使用sql 会有点慢, 如果使用 oracle 可能会好点

一、 把直接以二进制形式存储在数据库中

一般数据库提供一个二进制字段来存储二进制数据。比如SQL Server中的BINARY,VARBINARY;

1、BINARY 数据类型用于存储二进制数据。其定义形式为BINARY( n), n 表示数据的长度,取值为1 到8000 。在使用时必须指定BINARY 类型数据的大小,至少应为1 个字节。BINARY 类型数据占用n+4 个字节的存储空间。

在输入数据时必须在数据前加上字符“0X” 作为二进制标识,如:要输入“abc ”则应输入“0xabc ”。若输入的数据过长将会截掉其超出部分。若输入的数据位数为奇数,则会在起始符号“0X ”后添加一个0,如上述的“0xabc ”会被系统自动变为“0bc”。

2、VARBINARY数据类型的定义形式为VARBINARY(n)。 它与BINARY 类型相似,n 的取值也为1 到8000, 若输入的数据过长,将会截掉其超出部分。

不同的是VARBINARY数据类型具有变动长度的特性,因为VARBINARY数据类型的存储长度为实际数值长度+4个字节。当BINARY数据类型允许NULL 值时,将被视为VARBINARY数据类型。

一般情况下,由于BINARY 数据类型长度固定,因此它比VARBINARY 类型的处理速度快

另,MySQL中有个blob字段。Oracle数据库中是blob或bfile类型

sql server 中的image数据类型可以进行数据的存储,其中存储8张的方法为:

1、首先展开可编程性下面的用户定义数据类型是空的。

2、接着选择数据库,点击顶部的新建查询按钮。

3、然后直接用sp_addtype语句进行数据类型的定义。

4、接下来刷新用户自定义数据类型,这次就有数据了。

5、接着右键数据表选择设计选项。

6、最后就可以在数据类型里面找到自定义的数据类型了。

注意事项:

SQL Server将支持丰富的全文应用软件。服务器的编目功能将得到增强,对编目的对象提供更大的灵活性。查询性能和可升级性将大幅得到改进,同时新的管理工具将为有关全文功能的运行,提供更深入的了解。

原来你是做网站啊,呵呵,Dreamweaver 是不能胜任的,你需要写个

VBS,你也可以在网上直接下一个现成的,自己写也很麻烦

你在网上搜索一下这个吧,也许能给你启发哦

爱雪儿文件上传系统 Version 300

>

看情况了:

1:放于数据库中,只合适容量小的。如果有成千上万张,你就知道这个数据库有多大了,它将吃掉你服务器的很多资源。得不尝失。

2:放于目录中,路径放于数据库中,合适数量大的。但是同样的编程水平安全性没有前者高。

主要是看你那种情况了。

背景

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

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

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

举例

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

root@ytt:/var/lib/mysql-files# ls -sihl 微信_20190711095019jpg274501 54M -rw-r--r-- 1 root root 54M Jul 11 07:17 微信_20190711095019jpg

拷贝 100 份这样的来测试

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

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

100jpg   17jpg  25jpg  33jpg  41jpg  4jpg   58jpg  66jpg  74jpg  82jpg  90jpg  99jpg  f8tsv

10jpg    18jpg  26jpg  34jpg  42jpg  50jpg  59jpg  67jpg  75jpg  83jpg  91jpg  9jpg   微信_20190711095019jpg

1111jpg  19jpg  27jpg  35jpg  43jpg  51jpg  5jpg   68jpg  76jpg  84jpg  92jpg  f1tsv

11jpg    1jpg   28jpg  36jpg  44jpg  52jpg  60jpg  69jpg  77jpg  85jpg  93jpg  f2tsv

12jpg    20jpg  29jpg  37jpg  45jpg  53jpg  61jpg  6jpg   78jpg  86jpg  94jpg  f3tsv

13jpg    21jpg  2jpg   38jpg  46jpg  54jpg  62jpg  70jpg  79jpg  87jpg  95jpg  f4tsv

14jpg    22jpg  30jpg  39jpg  47jpg  55jpg  63jpg  71jpg  7jpg   88jpg  96jpg  f5tsv

15jpg    23jpg  31jpg  3jpg   48jpg  56jpg  64jpg  72jpg  80jpg  89jpg  97jpg  f6tsv

16jpg    24jpg  32jpg  40jpg  49jpg  57jpg  65jpg  73jpg  81jpg  8jpg   98jpg  f7tsv

我们建三张表,分别用 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 (000 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 (000 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 (000 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/mysqldsock -e "insert into ytttt_image1(image_file)

values (load_file('/var/lib/mysql-files/$ijpg'))";done;

tt_image2

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

do mysql -S /var/run/mysqld/mysqldsock -e "insert into ytttt_image2(image_file)

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

tt_image3

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

do aa=$aa"insert into ytttt_image3(image_file) values

('/var/lib/mysql-files/$ijpg');";

done;aa=$aa'commit;';mysql -S /var/run/mysqld/mysqldsock -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 (000 sec)

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

root@ytt:/var/lib/mysql/ytt# ls -silhS tt_image274603 11G -rw-r----- 1 mysql mysql 11G Jul 11 07:27 tt_image2ibd274602 545M -rw-r----- 1 mysql mysql 544M Jul 11 07:26 tt_image1ibd274605  80K -rw-r----- 1 mysql mysql 112K Jul 11 07:27 tt_image3ibd

那么怎么把取出来呢?

tt_image3 肯定是最容易的

mysql> select from tt_image3;+----+----------------------------+| id | image_file                 |+----+----------------------------+|  1 | /var/lib/mysql-files/1jpg |+----+----------------------------+100 rows in set (000 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 来存放的例子,总的来说有以下三点:

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

使用不易

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

以上就是关于分析大文本与图像数据在数据库内部的存储原理。全部的内容,包括:分析大文本与图像数据在数据库内部的存储原理。、目前大型的图片网站,都什么用哪种数据库存储图片的、在数据库中可用来存储图片的字段对象是哪种类型的字段等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9833808.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-02
下一篇 2023-05-02

发表评论

登录后才能评论

评论列表(0条)

保存