时间:2021-10-30来源:本站原创作者:佚名
EDM营销求职招聘QQ群 http://liangssw.com/shishang/13036.html

译者简介

晏杰宏,任职于上海新炬网络信息技术股份有限公司,OracleDBA。负责数据库、中间件、大数据等基础软件建设、优化和业务保障工作。具有0年以上电信与银行企业一线/二线数据库运维管理经验。目前专注研究云计算、开源软件和国产化数据库等领域技术研究。

校对者简介

崔鹏,任职于海能达通信股份有限公司,数据库开发高级工程师,致力于postgresql数据库在专网通信领域、公共安全领域的应用与推广。

PostgreSQL提供了一个很好的BLOB接口,它被广泛使用。但是,最近我们遇到了各种客户面临的问题,有必要进行反思并弄清楚PostgreSQL如何处理二进制大对象,尤其是二进制大对象清理,这是很有意义的。使用PostgreSQLBLOB接口在PostgreSQL中,您可以使用各种方法来存储二进制数据。最简单的形式肯定是利用“bytea”(字节数组)数据类型。在这种情况下,二进制字段基本上被视为行的一部分。下面是它的工作原因:

test=#CREATETABLEt_image(idint,nametext,imagebytea);CREATETABLEtest=#\dt_imageTable"public.t_image"Column

Type

Collation

Nullable

Default-------+---------+-----------+----------+---------id

integer

name

text

image

bytea

正如你所看到的,这是一个普通列,可以像普通列一样使用。唯一值得一提的是必须在SQL级别使用的编码。PostgreSQL使用变量来配置此行为:

test=#SHOWbytea_output;bytea_output--------------hex(row)bytea_output变量接受两个值:“hex”告诉PostgreSQL以十六进制格式发送数据。“转义”表示必须将数据作为八进制字符串输入。除了每个字段GB的最大大小外,这里的应用程序不必担心。但是,PostgreSQL有另一个处理二进制数据的接口:BLOB接口。让我展示一下这个功能强大的工具的示例:

test=#SELECTlo_import(/etc/hosts);lo_import-----------(row)在这种情况下,/etc/hosts的内容已导入到数据库中。请注意,PostgreSQL有数据的副本–它不是文件系统的链接。这里值得注意的是,数据库将返回新条目的OID(对象ID)。为了跟踪这些OID,一些开发人员执行以下操作:

test=#CREATETABLEt_file(idint,nametext,object_idoid);CREATETABLEtest=#INSERTINTOt_fileVALUES(,some_name,lo_import(/etc/hosts))RETURNING*;id

name

object_id----+---------------+-----------

some_name

(row)个INSERT0这是绝对可以的,除非您执行以下操作:

test=#DELETEFROMt_fileWHEREid=;DELETE问题是对象id被遗忘了。但是,目标仍然存在。pg_largeobject是PostgreSQL中负责存储二进制数据的系统表。所有的lo_functions都将简单地与这个系统表交互,以便处理这些问题:

test=#\xExpandeddisplayison.test=#SELECT*FROMpg_largeobjectWHEREloid=;-[RECORD]------------------------------------------loid

pageno

0data

##\02#HostDatabase\02#\02#localhost...为什么会有问题呢?原因很简单:您的数据库将增长,并且“死对象”的数量将累积。因此,杀死BLOB条目的正确方法如下:

test=#\xExpandeddisplayisoff.test=#test=#SELECTlo_unlink();lo_unlink-----------(row)test=#SELECT*FROMpg_largeobjectWHEREloid=;loid

pageno

data------+--------+------(0rows)如果你忘了解除对象的链接,从长远来看,你将遭受损失——我们经常看到这种情况发生。如果使用BLOB接口,这是一个主要问题。vacuumlo:清理死的大对象然而,一旦你积累了上千个,甚至百万个死的二进制大对象,你该如何解决这个问题呢?答案是一个名为“vacuumlo”的命令行工具。让我们首先创建一个死条目

test=#SELECTlo_import(/etc/hosts);lo_import-----------(row)这样我们就可以在任何客户端运行vacuumlo:

iMac:~hsvacuumlo-hlocalhost-vtestConnectedtodatabase"test"Checkingobject_idinpublic.t_fileSuccessfullyremoved2largeobjectsfromdatabase"test".如你所见,有两个死物被这个工具杀死了。vacuumlo是清除孤立对象的最简单方法。附加功能但是,不仅有lo_import和lo_unlink。PostgreSQL提供了多种功能来很好地处理大型对象:

test=#\dflo_*ListoffunctionsSchema

Name

Resultdatatype

Argumentdatatypes

Type------------+---------------+------------------+---------------------------+------pg_catalog

lo_close

integer

integer

funcpg_catalog

lo_creat

oid

integer

funcpg_catalog

lo_create

oid

oid

funcpg_catalog

lo_export

integer

oid,text

funcpg_catalog

lo_from_bytea

oid

oid,bytea

funcpg_catalog

lo_get

bytea

oid

funcpg_catalog

lo_get

bytea

oid,bigint,integer

funcpg_catalog

lo_import

oid

text

funcpg_catalog

lo_import

oid

text,oid

funcpg_catalog

lo_lseek

integer

integer,integer,integer

funcpg_catalog

lo_lseek64

bigint

integer,bigint,integer

funcpg_catalog

lo_open

integer

oid,integer

funcpg_catalog

lo_put

void

oid,bigint,bytea

funcpg_catalog

lo_tell

integer

integer

funcpg_catalog

lo_tell64

bigint

integer

funcpg_catalog

lo_truncate

integer

integer,integer

funcpg_catalog

lo_truncate64

integer

integer,bigint

funcpg_catalog

lo_unlink

integer

oid

func(8rows)由于历史原因,还有两个不遵循命名约定的函数:loread和lowrite:

个2pg_catalog

loread

bytea

integer,integer

funcpg_catalog

lowrite

integer

integer,bytea

func这些函数的名字再也不能轻易改变了。然而,值得注意的是,它们确实存在。最后PostgreSQLBLOB接口确实非常有用,可以用于很多事情。它的优点在于它是完全事务性的,因此二进制内容和元数据不能再不同步了。
转载请注明原文网址:http://www.gzdatangtv.com/bbqb/bbqb/16421.html

------分隔线----------------------------