浅析Oracle 11g中对数据列默认值变化的优化

日常的运维工作中,对生产数据表进行DDL操作是一件需要谨慎对待的事情。运维DBA们在进行数据DDL操作的时候,通常要全局考虑,诸如对生产影响、执行时间长度和影响存储数据等等。 数据列默认值的添加,是DBA们经常头疼的一个问题。传统的执行语句,消耗时间

在日常的运维工作中,对生产数据表进行DDL操作是一件需要谨慎对待的事情。运维DBA们在进行数据DDL操作的时候,通常要全局考虑,诸如对生产影响、执行时间长度和影响存储数据等等。

数据列默认值的添加,是DBA们经常头疼的一个问题。传统的执行语句,消耗时间长、资源使用量大,对生产环境影响程度高。采用其他的一些变通方法,又存在操作步骤繁琐的问题。如何快速的添加一个有默认值的数据列,同时对现有生产环境影响最小,是我们希望达到的一个目标。

本文从操作入手,探讨添加default数据列的问题点,最后介绍Oracle 11g中对其进行的“革命性”优化

1、从10g的数据列添加谈起

为了实现对比效果,我们首选选择10g版本的Oracle进行试验,构造一个相对较大的数据表。

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

SQL> create table t as select object_id from dba_objects;
表已创建。

SQL> select count(*) from t;
COUNT(*)
———-
  3220352

数据表t只包括一个数据列,但是数据量大约为320万条。我们从体积上进行评估如下:

SQL> set timing on;
SQL> select bytes/1024/1024,blocks from dba_segments where wner=’SYS’ and segment_name=’T’;

BYTES/1024/1024    BLOCKS
————— ———-
            39      4992

已用时间: 00: 00: 00.03

SQL> exec dbms_stats.gather_table_stats(user,’T’,cascade=>true);
PL/SQL过程已成功完成。

已用时间: 00: 00: 00.35

SQL> select blocks from dba_tables where wner=’SYS’ and table_name=’T’;

   BLOCKS
———-
     4883

已用时间: 00: 00: 00.01

Oracle分配给这个段segment的中空间为4992个数据块,高水位线HWM下的格式化过数据块为4883。总体积约40M。

下面进行两种方式的添加数据表默认值列方法,一起观察一下变化情况。首先是允许为空默认值列的操作。

SQL> alter table t add vc varchar2(100) default ‘TTTTTTTTTTTT’;

表已更改。

已用时间: 00: 34: 37.15

SQL> exec dbms_stats.gather_table_stats(user,’T’,cascade=>true);

PL/SQL过程已成功完成。

已用时间: 00: 00: 03.86

SQL> select bytes/1024/1024,blocks from dba_segments where wner=’SYS’ and segment_name=’T’;

BYTES/1024/1024    BLOCKS
————— ———-
           208     26624

已用时间: 00: 00: 00.06
SQL> select blocks from dba_tables where wner=’SYS’ and table_name=’T’;

   BLOCKS
———-
    25864

已用时间: 00: 00: 00.01

果然是一个费时的操作,添加一个数据列默认值,总共消耗了近30分钟时间。原有数据表的体积也发生的膨胀,从原来的不到40M,上升到了208M。

这个现象告诉我们,当我们添加一个有default值的数据列,并且是直接添加的时候,一些数据被插入到了数据块中,引起空间膨胀。

在原有的结构下,数据添加到数据块上是必需的,只有这样才能将数据列default添加到里面去。

除了这个字句,我们是还可以提供数据列的not null选项,也是可以实现相同的功能的。

SQL> alter table t add vc2 varchar2(100) default ‘TTTTTTTTTTTT’ not null;

表已更改。

已用时间: 00: 15: 58.85

SQL> exec dbms_stats.gather_table_stats(user,’T’,cascade=>true);

PL/SQL过程已成功完成。

已用时间: 00: 00: 36.87

SQL> select bytes/1024/1024,blocks from dba_segments where wner=’SYS’ and segme
nt_name=’T’;

BYTES/1024/1024    BLOCKS
————— ———-
           256     32768

已用时间: 00: 00: 00.14
SQL> select blocks from dba_tables where wner=’SYS’ and table_name=’T’;

   BLOCKS
———-
    32448

已用时间: 00: 00: 00.04

也是消耗了15分钟,空间发生了很大程度变化。新空间分配,同时数据行数没有发生变化,潜在的行迁移(Row Migration)和行链接(Row Chaining)是严重恶化的!

综合分析Oracle 10g下的操作:为了添加上数据字段的默认值,Oracle会去访问每个数据块上的每个数据行进行数据列拓展工作,这个过程中还伴随着新空间分配和多余数据行复制。

这类型操作对于生产环境是恐怖的,在整个作业过程中,数据表结构被锁定,相关业务处理操作阻塞或者缓慢。所以,运维DBA都是选择在维护窗口或者变通的方法进行处理。

在Oracle 11g环境下,事情有了一些不同。

2、11g下的默认值配置

我们在11g上进行相似操作。

SQL> select * from v$version;
BANNER
——————————————————————————–
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 – Production

PL/SQL Release 11.2.0.1.0 – Production
CORE       11.2.0.1.0        Production

构建相似规模的数据表。

SQL> set timing on;
SQL> create table t as select object_id from dba_objects;
Table created

SQL> select count(*) from t;
COUNT(*)
———-
  3323167

SQL> exec dbms_stats.gather_table_stats(user,’T’,cascade => true);
PL/SQL procedure successfully completed

SQL> select segment_name, bytes/1024/1024, extents,blocks from user_segments where segment_name=’T’;

SEGMENT_NA BYTES/1024/1024   EXTENTS    BLOCKS
———- ————— ———- ———-
T                      40        55      5120

SQL> select NUM_ROWS, BLOCKS from dba_tables where wner=’SCOTT’ and table_name=’T’;

NUM_ROWS    BLOCKS
———- ———-
  3323167      5041

11g下我们准备了约330万数据,进行添加非空带默认值的数据列。

SQL> alter table t add vc2 varchar2(100) default ‘TTTTTTTTTTTT’ ;

alter table t add vc2 varchar2(100) default ‘TTTTTTTTTTTT’

ORA-01013:用户请求取消当前的操作

在添加defalut列,不指定not null的时候,数据持续时间超过了我们的想象。笔者主动将其断开了。下面试试添加not null时候。

–1s不到完成操作;
SQL> alter table t add vc varchar2(100) default ‘TTTTTTTTTTTT’ not null;
Table altered

Executed in 0.047 seconds

SQL> exec dbms_stats.gather_table_stats(user,’T’,cascade => true);
PL/SQL procedure successfully completed

SQL> select NUM_ROWS, BLOCKS from dba_tables where wner=’SCOTT’ and table_name=’T’;
NUM_ROWS    BLOCKS
———- ———-
  3323167      5041

Executed in 0 seconds

SQL> select segment_name, bytes/1024/1024, extents,blocks from user_segments where segment_name=’T’;

SEGMENT_NA BYTES/1024/1024   EXTENTS    BLOCKS
———- ————— ———- ———-
T                      40        55      5120

SQL> select * from t where rownum

OBJECT_ID VC
———- ——————————————————————————–
       20 TTTTTTTTTTTT
       46 TTTTTTTTTTTT
       28 TTTTTTTTTTTT
       15 TTTTTTTTTTTT
(篇幅原因,有省略……)
9 rows selected

我们发现,当执行not null的时候,Oracle以超乎想象的速度完成了过程。并且注意:数据表的体积没有发生任何变化!!但是,我们检查数据表的时候,却发现了对应列的默认值已经添加。

这个事情是比较奇怪的,有一个道理必然是可以说通:就是这个默认值在执行过程中,是绝对没有真正添加到数据块中的,因为只有这样才不会影响数据段的体积。

3、11g默认值处理的优化

那么,11g这个过程中是如何处理的呢?而且为什么只有添加Not null的时候才会有这个特点。我们从select数据行的trace进行入手。

我们选择10046跟踪一下select的全过程,看看显示出来的默认值从哪里来。

SQL> select value from v$diag_info where name=’Default Trace File’;

VALUE
———————————————————————–
/u01/diag/rdbms/wilson/wilson/trace/wilson_ora_6177.trc

SQL> alter session set events ‘10046 trace name context forever, level 12’;
会话已更改。

SQL> select * from t where rownum

OBJECT_ID
———-
VC
—————————————————————————–

SQL> alter session set events ‘10046 trace name context off’;
会话已更改。

对生成的trace文件进行处理,获取到tkprof结果。

D:\des>tkprof wilson_ora_6177.trc
output = res.txt

TKPROF: Release 10.2.0.1.0 – Production on星期五8月24 22:07:10 2012
Copyright (c) 1982, 2005, Oracle. All rights reserved.

在分析的结果中,我们发现很多的recursive语句,也就是Oracle为了执行这个SQL,连带运行了很多的语句,其中我们发现了一个“可疑”对象。

***********************************************************************

select binaryDefVal, length(binaryDefVal)
from
ecol$          where tabobj# = :1 and colnum = :2

call    count      cpu   elapsed      disk     query   current       rows
——- —— ——– ———- ———- ———- ———- ———-
Parse       1     0.00      0.00         0         0         0          0
Execute     1     0.00      0.00         0         0         0          0
Fetch       1     0.00      0.00         2         2         0          1
——- —— ——– ———- ———- ———- ———- ———-
total       3     0.00      0.00         2         2         0          1

ecol$是sys用户下的一个新添加的字典基表,其中内容如下:

SQL> desc ecol$;
Name        Type  Nullable Default Comments
———— —— ——– ——- ——–
TABOBJ#     NUMBER Y                       
COLNUM      NUMBER Y                       
BINARYDEFVAL BLOB  Y                       

SQL> select * from ecol$;

  TABOBJ#    COLNUM BINARYDEFVAL
———- ———- ————
    76046         2
Executed in 0.031 seconds

SQL> col owner for a10;
SQL> col object_name for a10;
SQL> select owner, object_name, object_id from dba_objects where object_id in (76046);

OWNER     OBJECT_NAM OBJECT_ID
———- ———- ———-
SCOTT     T              76046

Executed in 0 seconds

从ecol$数据表中,我们发现了对数据表T对象第二列(column=2)的一个对象引用,引用的值binarydefval是一个blob类型。从直观上,我们已经可以猜出这个就是记录了数据表vc列的默认值。

此处,我们说一个问题,在Oracle中,默认值都是通过大对象类型进行保存。在数据字典col$中,默认值是通过long类进行保存。而进入11g的ecol$表,这个值是使用blob类型进行保存。

另一个需要注意的,就是这个数据表中只有一个数据行,也就是只有我们创建数据表T的默认值。这说明什么呢?

此时,我们已经可以猜出Oracle的良苦用心。首先,Oracle注意到了在生产online的时候,添加带默认值列数据的困难。但是,从现有的体系结构和存储结构下,将默认值逐行插入、从而引起行迁移的情况是不能避免的。所以,Oracle采用了一种“障眼法”。

如果我们在创建数据表的时候就指定了数据列的默认值、或者没有要求将所有数据空值一次性全都变成默认值的时候,Oracle还是按照原有的存储策略进行管理。如果出现了要求添加数据列,并且一次性将所有默认值列都加入的情况,Oracle索性就不进行插入数据和挪行的操作,而是将这个默认值保存在ecol$中。

接下来,如果要进行检索数据,首先Oracle会利用recursive call的方法,保存提取出默认值。在检索数据的过程中,如果遇到默认值列为空的情况(没有插值),就将取出的默认值输出到界面上进行显示。其实,数据行对应的默认值列是没有这个值的。

这就解释了为什么只有在添加not null默认值列的时候,才会有这个优化。因为Oracle需要确认这个列不会有空值,才会将出现的空值全都进行“障眼法”匹配。

4、结论

借助了11g这个特性,我们说在online生产环境下,临时加入默认值列就不是一件恐怖的工作了。不过,处于谨慎的考虑,还是希望有条件的时候,将该数据表进行重构。这种特性属于应急环境下考虑使用。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/467102.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
EyeCare工具如何备份配置文件_EyeCare护眼工具配置文件备份方法详述
上一篇 2025年11月8日 05:54:17
win10系统磁盘占用100%怎么解决_win10磁盘占满的优化方法
下一篇 2025年11月8日 05:54:19

相关推荐

  • php实现哪些功能

    PHP是一种通用脚本语言,可用来实现广泛的功能,包括:动态Web开发:生成响应用户请求的动态 веб页面。内容管理系统(CMS):构建允许用户管理网站内容的CMS。电子商务:开发具有购物车、订单处理和支付网关集成的电子商务网站。服务器端编程:编写命令行脚本和工具。文件操作:创建、读取、写入和删除文件…

    2026年5月10日
    000
  • SQL查询:精确判断事件过期,结合日期与时间列

    本文旨在解决数据库中事件过期判断不精确的问题,特别是当事件的过期日期和时间分别存储在不同列时。我们将探讨两种主流的sql查询策略:一种是利用逻辑运算符`or`和`and`进行分情况判断,另一种是通过合并日期和时间列为单一时间戳进行直接比较。文章将详细阐述每种方法的实现方式、适用场景及相关注意事项,确…

    2026年5月10日
    100
  • HTML表单如何实现白名单功能?怎样只允许授权用户?

    要实现%ignore_a_1%的白名单功能并确保只有授权用户操作,核心答案是必须依赖后端服务器进行严格的身份认证、会话管理、授权检查和数据验证,前端仅能提供用户体验层面的初步提示而不能保障安全;具体而言,首先通过用户身份认证(如用户名/密码或oauth)确认用户身份,服务器创建会话并返回标识符,后续…

    2026年5月10日
    800
  • 如何用C#实现数据库的跨平台迁移?使用EF Core工具?

    使用EF Core实现跨平台数据库迁移,需定义实体与DbContext,通过动态配置不同数据库提供程序,利用EF Core CLI生成并应用迁移,结合Fluent API处理数据库差异,确保结构与数据兼容。 要实现数据库的跨平台迁移,C# 中最常用且高效的方式是使用 Entity Framework…

    2026年5月10日
    000
  • Python连接MySQL 5.1:克服旧版认证与字符集兼容性挑战

    本教程详细阐述了如何使用Python 3和mysql.connector库成功连接到老旧的MySQL 5.1数据库。文章重点介绍了解决旧版认证协议和字符集兼容性问题的关键配置,特别是use_pure=True和charset=’utf8’的重要性,并提供了可运行的代码示例。同…

    2026年5月10日
    000
  • 想提升IT技能?哪些含金量高的认证值得考?

    it职业发展:高含金量认证助您成功 想在IT领域提升竞争力?选择合适的认证至关重要。本文推荐几项国内外认可度高的IT认证,助您在职业道路上更进一步。 热门认证推荐: 1. 高级软件设计师(软考高级): 国内IT领域含金量最高的认证之一。涵盖软件工程、项目管理及计算机基础知识。证明您在软件设计和开发方…

    2026年5月10日
    000
  • js 怎样用defaults为对象数组添加默认值

    为 javascript 对象数组添加默认值的核心方法有三种:1. 使用 object.assign() 将默认值合并到每个对象的副本中,确保原始数据不变;2. 使用扩展运算符 ({ …defaults, …item }) 实现更简洁的浅层合并;3. 使用 lodash 的 …

    2026年5月10日
    000
  • 什么是资产代币化(Asset Tokenization)?它如何将现实世界资产带入区块链?

    资产代币化是通过区块链将房产、股票等实体资产权益转化为可分割的数字代币。首先选择目标资产并由合规机构确权估值,随后在链上发行对应代币并通过智能合约绑定权益比例,实现自动化分红与转让。为确保真实性,引入第三方审计和去中心化预言机同步链下数据,资金流由托管账户与链上地址联动记录,提升透明度。代币化降低投…

    2026年5月10日
    000
  • 如何高效地在Go中使用http.ResponseWriter构建JSONP响应

    本教程探讨在go语言中高效构建jsonp响应的方法,重点解决如何使用`http.responsewriter`处理回调函数封装。文章通过对比传统字符串拼接与字节切片转换的不足,详细介绍了利用`fmt.fprintf`直接写入和`fmt.sprintf`预格式化两种优化方案,旨在提升代码的简洁性和执行…

    2026年5月10日
    000
  • MySQL、PostgreSQL、SQL Server和Oracle中空字符串、数字0和NULL占用空间有何区别

    不同数据库系统中空字符串、数字0和NULL的存储空间差异 本文比较了MySQL InnoDB、PostgreSQL、SQL Server和Oracle数据库中,空字符串(”)、数字0和NULL值在磁盘上所占用的空间大小。 MySQL InnoDB存储引擎: 整型字段: NULL: 不占用…

    2026年5月10日
    000
  • html文档中含有java怎么运行_html含java运行方法【教程】

    现代浏览器不支持Java Applet,推荐通过JavaScript调用Java后端服务或使用WebAssembly运行Java代码。 如果您在HTML文档中嵌入了Java代码,但发现无法正常运行,这通常是因为现代浏览器不再支持Java小程序(Applet)或相关插件。以下是几种实现HTML中Jav…

    2026年5月10日
    000
  • php主要运用哪些东西

    PHP 是一种通用脚本语言,主要用于 Web 开发,包括创建动态网页、网站框架和内容管理系统。此外,它还支持 Web 服务(RESTful 和 SOAP)、数据库操作、命令行脚本、桌面应用程序和图像处理。 PHP 语言的主要应用 PHP(超文本预处理器)是一种广泛应用的通用脚本语言,主要用于 Web…

    2026年5月10日
    100
  • 优化CSS解析过程中的回流和重绘技巧

    CSS回流和重绘解析及优化技巧 近年来,网页性能优化成为了前端开发中的重要环节,其中包括对CSS回流和重绘的解析及优化。在优化CSS的过程中,我们需要了解回流和重绘的定义,并学习一些具体的优化技巧。 什么是回流和重绘? 回流(reflow)和重绘(repaint)是浏览器渲染引擎对网页进行布局和绘制…

    2025年12月24日
    000
  • 优化网页加载速度的技巧:理解回流和重绘的差异与优化方法

    回流与重绘的差异与优化:优化网页加载速度的技巧 在如今互联网高速发展的时代,网页加载速度成了用户体验的重要指标之一。加载速度慢不仅会让用户感到不耐烦,还会导致用户流失,影响网站的转化率。而要提高网页的加载速度,我们就需要了解和优化回流与重绘。 回流(reflow)和重绘(repaint)是浏览器渲染…

    2025年12月24日
    300
  • 提高页面渲染速度:优化回流和重绘的关键方法

    提高页面渲染速度:优化回流和重绘的关键方法,需要具体代码示例 随着网页应用的发展,用户对页面加载速度的要求也越来越高。而页面的渲染速度受到回流和重绘的影响,因此我们需要优化这两个过程来提高页面的渲染速度。本文将介绍一些关键的方法,并提供具体的代码示例。 使用transform替代top/left当改…

    2025年12月24日
    400
  • 通过使用Web标准,提升网页性能与用户体验的方法

    随着互联网的快速发展,越来越多的企业和个人都开始关注网页的性能和用户体验。一方面,良好的网页性能可以提高网站的可访问性和搜索引擎排名,另一方面,优秀的用户体验可以增加用户的黏性和转化率。而借助Web标准来优化网页性能与用户体验,则成为现如今的一种主流方法。 那么,如何利用Web标准来优化网页性能与用…

    2025年12月24日
    300
  • 比较重排、重绘和回流的优化策略以提高网页性能

    优化网页性能:探讨重排、重绘和回流的优劣比较,需要具体代码示例 随着互联网的发展,网页性能优化已成为每个前端开发人员需要面对的一个重要问题。在优化网页性能的过程中,我们需要了解并针对不同的操作进行优化。其中,重排、重绘和回流是导致网页性能下降的常见问题,本文将探讨它们的优劣,并给出一些具体的代码示例…

    2025年12月24日
    500
  • 使用关系型选择器优化CSS选择器:提升选择效率的技巧

    优化CSS选择器:如何使用关系型选择器提高选择效率 引言:在前端开发中,CSS选择器是一个非常重要的概念。它用来为HTML元素添加样式,控制页面的外观和布局。然而,在大型项目中,优化CSS选择器的效率显得尤为重要。本文将介绍如何使用关系型选择器来提高选择效率,并附上具体的代码示例。 一、什么是关系型…

    2025年12月24日
    000
  • 优化网页排版的CSS属性使用指南

    优化网页排版的CSS属性使用指南 在现代网页设计中,好的排版是不可或缺的一部分。正确使用CSS属性可以有效地改善网页排版的质量和用户体验。本文将为您介绍一些常用的CSS属性以及示例代码,帮助您优化网页排版。 一、字体属性 font-size:控制字体的大小,可以使用像素、百分比或者em作为单位。例如…

    2025年12月24日
    000
  • CSS 清除样式属性优化技巧:reset 和 normalize

    CSS 清除样式属性优化技巧:reset 和 normalize 在开发网页时,经常会遇到浏览器默认样式的干扰,导致网页显示效果不一致。为了解决这个问题,我们可以使用 CSS 清除样式属性的优化技巧。本文将介绍两种常用的方式:reset 和 normalize,并提供具体的代码示例。 一、Reset…

    2025年12月24日
    100

发表回复

登录后才能评论
关注微信