Oracle Lob类型存储浅析-程序员宅基地

技术标签: 运维  操作系统  数据库  

 

Oracle中,为数据表字段columnPL/SQL语言,分别提供了多种数据类型,以应对实际开发中的多种类型。Lob类型是Oracle推出一种保存大对象的数据类型。当我们考虑将信息文件(十进制、二进制)、图像甚至音频信息采用数据库作为保存载体时,就需要使用lob类型数据。

 

目前Oracle支持的Lob类型具体包括四个子类型(subtype),分别为CLOBBLOBNLOBBFILE。其中,CLOBBLOBNLOB都是将数据保存在数据库内部,而BFILE类型保存的核心是文件指针,真正的文件是保存在数据库外。

 

与传统的数据类型相比较,lob类型数据无论在管理上还是空间使用上,都有很多特殊之处。本篇主要介绍lob类型一些基本的存储特性。

 

1、  环境准备和数据段segment特性

 

我们选择在Oracle 10gR2下进行试验。

 

 

SQL> select * from v$version;

 

BANNER

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

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod

PL/SQL Release 10.2.0.1.0 - Production

CORE     10.2.0.1.0       Production

 

TNS for 32-bit Windows: Version 10.2.0.1.0 - Production

NLSRTL Version 10.2.0.1.0 – Production

 

 

使用create table命令,可以构建出一个实验数据表T

 

 

SQL> create table t (id number, cl clob);

Table created

 

 

对于一般的数据表而言,一个数据表只会对应一个存储数据段data segment对象。这里的特殊情况是分区表,通常一个分区就对应一个单独的存储对象。当数据表中包括lob类型的数据列时,也会有独特的段对象建立。

 

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

SYS_LOB0000056069C00002$$      LOBSEGMENT USERS

T                              TABLE      USERS

SYS_IL0000056069C00002$$       LOBINDEX   USERS

(篇幅原因,无关对象省略。。。。。。)

 

9 rows selected

 

 

我们发现,除了常规的数据段T之外,另外增加了两个明显是系统命名的段对象,类型分别为lobsegmentlobindex

 

Oracle lob类型数据表而言,一个带lob列的数据表创建是要对应多个数据段创建的。除了传统的数据表创建的数据段Table Data Segment之外,一个lob列都会生成两个专门的段:lob段和lob索引段。

 

Lob段(LobSegment)对应的是存放在数据表lob列上的数据。在Oraclelob类型数据列,有两种保存位置结构。一个是in-row storage,也就是每一行的lob数据同其他列的数据以行的形式一起保存在数据块中。这种情况的lob列取值较小。而另一种为out-of-row storage,当lob对象较大,不能保存在一个数据块中时,可以将其放置在一个独立lobsegment中进行保存。而out-of-row storage时数据行中lob列上保存的只是一个指向lobsegment对应位置的指针引用。

 

Lob索引段(LobIndex)是Oracle为每一个lob类型列强制生成的索引,主要作用是用于进行lob类型数据检索加速的操作。Lobindexlob列共生,如果强制进行删除操作,是会报错的。

 

 

SQL> drop index SYS_IL0000056069C00002$$;

drop index SYS_IL0000056069C00002$$

 

ORA-22864: 无法 ALTER DROP LOB 索引

 

 

 

2lob类型数据表原始定义分析

 

使用dbms_metadata包,我们可以获取到数据表的全部定义,包括各种缺省参数和细节信息。

 

 

CREATE TABLE "SCOTT"."T"

   ( "ID" NUMBER,

       "CL" CLOB

   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING

  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)

  TABLESPACE "USERS"

 LOB ("CL") STORE AS (

  TABLESPACE "USERS" ENABLE STORAGE IN ROW CHUNK 8192 PCTVERSION 10

  NOCACHE LOGGING

  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)) ;

 

  CREATE UNIQUE INDEX "SCOTT"."SYS_IL0000056069C00002$$" ON "SCOTT"."T" (

  PCTFREE 10 INITRANS 2 MAXTRANS 255

  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)

  TABLESPACE "USERS"

  PARALLEL (DEGREE 0 INSTANCES 0) ;

 

 

可以看到我们抽取出的元数据包括两个组成部分,数据表创建部分和lob索引创建部分。在数据表创建部分,我们可以看到将lob作为一个独立段对象进行存储设置和参数设置。

 

lob索引创建部分,我们可以看到虽然是对应索引创建语句,但是从索引名称上显然是系统自动生成的对象名称。

 

此外,还有很多是针对lob特殊的参数,如cacheenable storage in-row等,这些参数在数据表lob的行为和访问性能上有巨大的影响。由于篇幅和内容所限,我们在本篇中不加以累述。

 

 

3lob段与lob索引存储转移

 

对于一个数据表涉及的多个段,很多时候我们需要将其进行移动处理。其中最常用的方法是使用move进行对象表空间的移动。

 

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

SYS_LOB0000056099C00002$$      LOBSEGMENT USERS

T                              TABLE      USERS

SYS_IL0000056099C00002$$       LOBINDEX   USERS

 

9 rows selected

 

SQL> alter table t move tablespace system;

 

Table altered

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

T                              TABLE      SYSTEM

SYS_LOB0000056099C00002$$      LOBSEGMENT USERS

SYS_IL0000056099C00002$$       LOBINDEX   USERS

 

9 rows selected

 

 

上面实验可以明确看到,当使用一般的move命令时,只会将数据表T段进行移动到新表空间。Lob段和对应的lobindex段没有变化。如果需要移动lob/lobindex,需要额外的单独操作。

 

 

SQL> alter index SYS_IL0000056069C00002$$ rebuild tablespace users;

alter index SYS_IL0000056069C00002$$ rebuild tablespace users

 

ORA-02327: 无法以数据类型 LOB 的表达式创建索引

 

 

Lobindex是不能使用rebuild直接重构的。

 

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

T_LOGSEGMENT                   LOBSEGMENT USERS

SYS_IL0000056069C00002$$       LOBINDEX   USERS

T                              TABLE      EXAMPLE

 

9 rows selected

 

SQL> alter table t move lob(cl) store as t_logsegment (tablespace example);

 

Table altered

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

T                              TABLE      EXAMPLE

SYS_IL0000056069C00002$$       LOBINDEX   EXAMPLE

T_LOGSEGMENT                   LOBSEGMENT EXAMPLE

 

9 rows selected

 

 

使用alter table xxx move lob(xx) store as xxx (tablespace xxx);命令,我们可以进行lob列的存储位置调节。

 

在创建数据表的时候,同样可以使用lob(xxx)对应的数据表空间字句,执行存储lob对象的空间信息。

 

 

SQL> Create table DemoLob ( A number, B clob )

  2         LOB(b)

  3       STORE AS lobsegname (

  4         TABLESPACE users

  5         --STORAGE (lobsegment storage clause)

  6         INDEX lobindexname (

  7              TABLESPACE example

  8              --STORAGE ( lobindex storage clause )

  9         )

 10       )

 11        TABLESPACE system

 12       --STORAGE( tables storage clause )

 13       ;

 

Table created

 

SQL> select table_name, column_name, segment_name, tablespace_name, index_name from user_lobs;

 

TABLE_NAME COLUMN_NAM SEGMENT_NAME                   TABLESPACE_NAME                INDEX_NAME

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

T          CL         T_LOGSEGMENT                   EXAMPLE                        SYS_IL0000056069C00002$$

 

 

在实际物理设计部署过程中,经常有将大对象分区和存储单独部署表空间的情况。可以根据实际的情况,将一些很大的lob列连同索引保存在单独的表空间上。

 

但是注意,一般数据表而言,lob段和lobindex段是在一个表空间上。即使在SQL语法上存在支持,但是将lob段和lobindex分开存储的语句通常被忽略掉。

 

 

 

SQL> alter table t move lob(cl) store as T_LOGSEGMENT (tablespace example index t_logindex (tablespace users));

 

Table altered

 

SQL> select table_name, column_name, segment_name, tablespace_name, index_name from user_lobs;

 

TABLE_NAME COLUMN_NAM SEGMENT_NAME                   TABLESPACE_NAME                INDEX_NAME

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

T          CL         T_LOGSEGMENT                   EXAMPLE                        SYS_IL0000056069C00002$$

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

T                              TABLE      EXAMPLE

SYS_IL0000056069C00002$$       LOBINDEX   EXAMPLE

T_LOGSEGMENT                   LOBSEGMENT EXAMPLE

 

9 rows selected

 

 

4、结论

 

Lob类型是一种我们经常使用的复杂数据类型。处理和管理lob类型的方法和我们常规的手段存在很大差异,无论是开发还是运维过程中都要特别注意。

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_33869377/article/details/90247914

智能推荐

ESP8266和ESP32区别,以及优缺点分析!_esp8266为什么不建议使用-程序员宅基地

文章浏览阅读3.4k次,点赞3次,收藏4次。高速主频240MHZ,对比STM32F1的72MHZ和STM32F4的168MHZ,速度快很多,而且价格上比起一直在涨价的STM系低出非常多;总的来说,STM32在国内的使用程度和受众程度是远大于ESP32的,毕竟STM32已经占据主流市场很久了,学习的资料比起ESP32起来会多,再加上一些开源问题,使用32的人群还是占据多数。2016年,乐鑫推出了ESP32,它是ESP8266的升级版本,速度更快还带有蓝牙4.2和蓝牙低功耗,价格在20元左右,在这个价格下几乎找不到对手可以“一战”。_esp8266为什么不建议使用

linux 分区简介,Linux硬盘分区知识简介-程序员宅基地

文章浏览阅读990次。Linux系统可以挂载多个不同接口类型的磁盘(disk),每一个磁盘又可以分成若干个分区(Partition),每个分区又可以拥有自己的文件系统类型(FileSystem)。Linux对于磁盘和分区又自己的一套标记方法。硬盘和分区的区分第一个SCSI(Small Computer System Interface)磁盘记为/dev/sda,第二个SCSI磁盘记为/dev/sdb;第一个SATA磁盘..._linux引导分区的标记可为

unity 网络游戏架构设计(第12课:网络游戏案例讲解)之美_网络游戏消息结构设计案例-程序员宅基地

文章浏览阅读656次。第12课:网络游戏案例讲解上章给读者介绍关于服务器之间的通信,本章通过案例给读者介绍如何将框架跟 Photon 结合起来,实现一个网络通信的框架设计。UI 架构设计模块已经介绍过,我们的 Demo 使用的 UI 是 UGUI,简单的用几个 Button 代替 Sprite,它们的原理是一样的。我们先创建一个 UI,如下图所示:这个 UI 主要有三个关键按钮,分别是 Create Roo..._网络游戏消息结构设计案例

Android-Gradle详解_grade编译运行安卓-程序员宅基地

文章浏览阅读548次。Android 构建系统非常灵活,可让你在不修改应用核心源代码文件的情况下执行自定义构建配置。本部分将介绍 Android 构建系统的工作原理,以及它如何帮助你对多个构建配置进行自定义和自动化处理。构建过程涉及许多将你的项目转换为 Android 应用程序包 (APK) 的工具和过程。构建过程非常灵活,因此了解一些幕后发生的事情很有用。下图为Android 应用模块的构建过程。Android 应用模块的构建过程(如上图所示)遵循以下一般步骤:1、编译器将你的源代码转换为 DEX(Dalv_grade编译运行安卓

linux网络配置后面加一条wheel,linux安全配置/etc/sudoers&wheel组-程序员宅基地

文章浏览阅读800次。/etc/sudoers 控制哪些用户能在哪些主机上以哪些用户的身份执行哪些命令。只有此文件权限为440时才能用户才能使用sudo命令,只有root用户才能使用visudo命令修改此文件。当然也可以先添加文件写权限,然后修改,再把文件权限改回来。此文件的一些配置规则定义别名:User_Alias UserName = user1,user2,kongoveHost_Alias HostName =..._%wheel all=(all) all

NO.15——使用Appium自动化测试爬取微信朋友圈数据_appium监测微信图片-程序员宅基地

文章浏览阅读9.7k次,点赞5次,收藏27次。 一、解析过程本人使用锤子手机做测试,型号是YQ601,首先打开开发者模式确保手机能与mac相连,打开Appium客户端,配置参数如图可以理解为Appuim继承自web端的selenium,同样可以执行一些自动化操作。Appium自带了一个XPATH选择器,给用户提供了选择结果,如图这个选择器给出的结果太繁琐,所以可以改成通过查找ID的方式来构造爬虫程序。但是这里要注意,估计微信提升了自己..._appium监测微信图片

随便推点

交叉编译工具 aarch64-linux-gnu-gcc 的介绍与安装-程序员宅基地

文章浏览阅读8w次,点赞20次,收藏160次。aarch64-linux-gnu-gcc 是由 Linaro 公司基于 GCC 推出的的 ARM 交叉编译工具_aarch64-linux-gnu-gcc

数码管扫描显示verilog_如何开始Xilinx FPGA开发之旅 第二课 EGO1数码管与键盘-程序员宅基地

文章浏览阅读1.4k次。庚子年,我们的EGO1在疫情当中作为口袋实验平台成为了众多高校的复课利器。其中的成功案例更是得到了新华社网媒与CCTV教育频道的报道。借此东风,为了让更多的老师与学生熟悉了解Xilinx,更好的入门学习FPGA知识,我们的师资培训直播已开设EGO1专题直播,欢迎新老朋友跟踪关注。第二课---- EGO1数码管与键盘本周的直播我们将介绍EGO1的外设使用案例,介绍数码管扫描的原理和PS/2..._fpgaego1 键盘

python re库安装_python 库安装方法及常用库-程序员宅基地

文章浏览阅读3.6k次。python库安装方法:方法一:setpu.py1.下载库压缩包,解压,记录下路径:*:/**/……/2.运行cmd,切换到*:/**/……/目录下3.运行setup.py build4.然后输入python,进入python模块,验证是否安装成功方法二:1.Win + R 打开运行窗口,输入cmd回车2.找到pip安装路径——x:\Python xx\Scripts3. 在命令行中切换至该目录c..._rep库怎么安装

android listview fling,ListView优化: Fling(松开滑动) 过程中不加载数据-程序员宅基地

文章浏览阅读189次。1.Adapter增加滑动结束以后刷新方法//定义当前listview是否在滑动状态private boolean isScrolling = false;public void setScrolling(boolean scrolling) {this.isScrolling = scrolling;}public void refreshOnScrollEnd(AdapterView list..._android listview fling

微信公众号JSAPI自费支付总结_微信自动续费api-程序员宅基地

文章浏览阅读535次。文章目录前言一、准备操作1.公众号ID2.商户号3.商户号密钥4.域名、服务器二、步入正题1. 支付流程2. 初始化订单数据2.读入数据总结前言本编章主要是通过运行一个自费测试demo使其能够快速了解微信自费支付的实现流程,也是个人实现微信自费demo之后的记录、总结官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1一、准备操作进行微信自费支付之前请先获得以下几项必要条件,公众号和商户号需要绑定名称_微信自动续费api

java byte 字节负数-程序员宅基地

文章浏览阅读2w次。由于通讯协议中长度使用byte字节来表示,但在java中长度超过127的时候会变成负数,所以需要保证得到的长度是正数byte b & 0xFFhttp://www.blogjava.net/orangelizq/archive/2008/07/20/216228.html在剖析该问题前请看如下代码public static String bytes2HexString(

推荐文章

热门文章

相关标签