MySQL和Oracle的添加字段的处理差别

昨天在微信群中有个朋友也是无意中问了一下,说数据库中的表字段想保持一种相对规范的顺序,怎么办?要知道Oracle中这个操作就比较纠结了,因为是按照追加的方式来处理的。没法在已有的字段1,字段2中间添加一个字段3。但是MySQL却可以,这个方面MySQL看起来要灵活的多,这个是什么原因呢,他们在设计上有什么差别呢。
MySQL中对每个表存在一个定义文件,即frm文件,我们来取出一个表,看看能不能简单解析一下。
比如一个表字段的内容如下:
> desc zd_warshrine_prostate;
+----------+--------------+------+-----+-------------------+----------------+
| Field    | Type         | Null | Key | Default           | Extra          |
+----------+--------------+------+-----+-------------------+----------------+
| id       | int(10)      | NO   | PRI | NULL              | auto_increment |
| proName  | varchar(100) | NO   | MUL | NULL              |                |
| TYPE     | varchar(10)  | NO   |     | NULL              |                |
| loaderr  | int(11)      | NO   |     | 0                 |                |
| loadTime | timestamp    | NO   |     | CURRENT_TIMESTAMP |                |
+----------+--------------+------+-----+-------------------+----------------+
我们可以使用strings来简单解析一下,可以通过上面的内容能够读到一些信息。
# strings  zd_warshrine_prostate.frm
PRIMARY
in_ty_zyl_proName
InnoDB
)                                        
proName
TYPE
loaderr
loadTime
proName
TYPE
loaderr
loadTime
大体能够看出,只解析出来了字段名。而查看MySQL中的数据字典columns,却压根看不到column_id这样的字段。

在MySQL要实现添加字段的顺序性,语句可以这样写:
ALTER TABLE test
    ADD COLUMN `amount_sum`  double(255,0) AFTER `amount_name`;
即在字段amount_name后添加字段amount_sum
难道是MySQL中的这种方式技高一筹,也不是了,对于添加字段,修改数据类型这类的操作,MySQL在早期版本也是饱受诟病,因为会直接锁表,而且实现起来的思路其实就是复制表数据,类似于重建。这个情况在后来的一些版本比如5.6有了一些改善,有了pt-osc的工具,这个改进可以在线修改了。而实现方式其实有点类似于Oracle中的在线重定义,MySQL中会创建一个临时表,然后创建2个触发器,然后同步数据到临时表,然后触发器同步操作。如果表数据不大,倒还不是什么大问题,一旦数据量级上来了,业务关注度上来了,这个地方就值得好好挖掘挖掘。
Oracle中是怎么做的呢。看起来还是有不小的差别。
比如我们查看一个表users的数据。
SQL> select dbms_rowid.ROWID_RELATIVE_FNO(rowid) as file#,dbms_rowid.ROWID_BLOCK_NUMBER(rowid) as block#,dbms_rowid.ROWID_ROW_NUMBER(rowid) as row#,a.* from test.USERS a where rownum<2;
     FILE#     BLOCK#       ROW#     USERID USER_NAME
---------- ---------- ---------- ---------- --------------------
        24    1569619          0       1278 user1278
通过上面的输出可以看到是在24号文件,数据块1569619中,数据信息也一并输出出来了,这个表含有两个字段,userid,user_name;
那么数据是如何存储的呢。我们做一个dump
alter system dump datafile 24 block 1569619;        
为了图省事,可以直接查看select *from v$diag_info;得到trace文件的路径。
/U01/app/oracle/diag/rdbms/mbionline/mbionline/trace/mbionline_ora_15752.trc
我们输出几行trace文件的内容,可以看到字段都是存在一个column_id的字样,即col 0,col 1这样的。
tab 0, row 56, @0x134a
tl: 16 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 3]  c2 0e 23
col  1: [ 8]  75 73 65 72 31 33 33 34
tab 0, row 57, @0x135a
tl: 16 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 3]  c2 0e 24
col  1: [ 8]  75 73 65 72 31 33 33 35
tab 0, row 58, @0x136a
tl: 16 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 3]  c2 0e 25
col  1: [ 8]  75 73 65 72 31 33 33 36

Oracle中是按照这个column_id来进行字段的顺序管理的。关于字段有两个很相似的数据字典dba_tab_cols,tab_tab_columns。
里面很重要的一个属性就是column_id,同时也能够看出还有数据类型为Long的字段 DATA_DEFAULT ,这也算是Oracle为此问题付出的一个代价,为了保持兼容性,这个long类型的字段到了12c依旧是如此。
SQL> desc dba_tab_columns
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 OWNER                                     NOT NULL VARCHAR2(30)
 TABLE_NAME                                NOT NULL VARCHAR2(30)
 COLUMN_NAME                               NOT NULL VARCHAR2(30)
 DATA_TYPE                                          VARCHAR2(106)
 DATA_TYPE_MOD                                      VARCHAR2(3)
 DATA_TYPE_OWNER                                    VARCHAR2(60)
 DATA_LENGTH                               NOT NULL NUMBER
 DATA_PRECISION                                     NUMBER
 DATA_SCALE                                         NUMBER
 NULLABLE                                           VARCHAR2(1)
 COLUMN_ID                                          NUMBER
 DEFAULT_LENGTH                                     NUMBER
 DATA_DEFAULT                                       LONG
 NUM_DISTINCT                                       NUMBER
而如果对一个大表添加字段,如果涉及默认值,那就工作就很难了,除此之外添加字段方面,Oracle处理起来还是要好很多,至少不会重建表数据。这也算是两者在设计上的一些差别吧。而对于Oracle可以有不少的诊断方式,对于MySQL似乎方式和手段就少了一些,不过也有几种方式,
比如验证MySQL对于添加字段,修改数据类型,可以查看show processlist,找到一个线程会标示copy to tmp table
而同时在数据目录下会创建两个临时文件,类似下面的形式。
-rw-rw---- 1 mysql mysql        8860 Nov  4 19:15 #sql-2721_17a3a9.frm
-rw-rw---- 1 mysql mysql   549453824 Nov  4 19:16 #sql-2721_17a3a9.ibd
而更进一步想看到更多的内容,那就是源代码了,其实还好了,已经看到有些牛人在解析这部分的内容了,不过我得自己读一读,消化一下,才能拿出来。

时间: 2024-07-28 19:12:49

MySQL和Oracle的添加字段的处理差别的相关文章

MySQL和Oracle中的唯一性索引从差别(r12笔记第83天)

   今天在修复MySQL数据的时候,发现一个看起来"奇怪"的问题.   有一个表里存在一个唯一性索引,这个索引包含3个列,这个唯一性索引的意义就是通过这3个列能够定位到具体1行的数据,但是在实际中却发现这个唯一性索引还是有一个地方可能被大家忽略了.  我们先来看看数据的情况.  CREATE TABLE `test_base_data` (   `servertime` datetime DEFAULT NULL COMMENT '时间',   `appkey` varchar(64

paip.解决 数据库mysql增加列 字段很慢添加字段很慢

paip.解决 数据库mysql增加列 字段很慢添加字段很慢 环境如下: mysql5.6 数据仅仅3w alter table xxx add column yyy int default 0; 添加字段很慢,好几份中都没有好.. 原因以及解决 [SQL] alter table grejx_def add column flag12 int default 0; 受影响的行: 0 不是那种lock–copoy–rewrite的方式.effeic row sh 0 ,为甚还是这么慢的是?? O

代码-MySql动态行转列,网上找的sql语句,需要再添加字段,求帮忙谢谢大家

问题描述 MySql动态行转列,网上找的sql语句,需要再添加字段,求帮忙谢谢大家 SELECT -> IFNULL(c1,'total') AS total, -> SUM(IF(c2='B1',c3,0)) AS B1, -> SUM(IF(c2='B2',c3,0)) AS B2, -> SUM(IF(c2='B3',c3,0)) AS B3, -> SUM(IF(c2='B4',c3,0)) AS B4, -> SUM(IF(c2='total',c3,0))

mysql给表添加字段的命令

  给表添加字段的命令: ? 1 alter table tableName add newColumn varchar(8) comment '新添加的字段' 在这句语句中需要注意的是,comment为注释,就像在java中//作用是一样的. comment后需要加单引号将注释引起来.

Jsp 连接 mySQL、Oracle 数据库备忘(Windows平台)

js|mysql|oracle|window|数据|数据库  Jsp 环境目前最流行的是 Tomcat5.0.Tomcat5.0 自己包含一个 Web 服务器,如果是测试,就没必要把 Tomcat 与 IIS 或 Apache 集成起来.在 Tomcat 自带的 Web 服务器下可以进行 Jsp 测试.    安装 Tomcat5.0 前需要安装 JDK(如果是 Windows server 2003 就必须安装 JDK,因为 Windows server 2003 是不带 JVM 的-Wind

由一条create语句的问题对比mysql和oracle中的date差别

今天开发的同事提交过来一个sql变更,在部署的时候发现了一个问题. 语句是一个简单的create语句 CREATE TABLE `test_user` (   `openid` varchar(64) NOT NULL,   `amount` varchar(11) DEFAULT 0,   `create_time` datetime DEFAULT CURRENT_TIMESTAMP,   `update_time` datetime DEFAULT CURRENT_TIMESTAMP,  

用PHP连mysql和oracle数据库性能比较

mysql|oracle|比较|数据|数据库|性能 用PHP连mysql和oracle数据库性能比较 测试硬件说明:测试使用的是我的爱机,配置如下:CPU:C433内存:128M硬盘:酷鱼2代20G 测试软件说明:WIN32下用的是windows nt server4,sp5,apache 1.3.12,php3.0.15和php4rc1,mysql 3.22.29,oracle 8.0.5linux下用的是bluepoint linux1.0, apache 1.3.12, php4rc1,m

MYSQL到ORACLE程序迁移的注意事项(转载)

mysql|oracle|程序 MYSQL到ORACLE程序迁移的注意事项                                                  2001-09     有很多应用项目, 刚起步的时候用MYSQL数据库基本上能实现各种功能需求,随着应用用户的增多,数据量的增加,MYSQL渐渐地出现不堪重负的情况:连接很慢甚至宕机,于是就有把数据从MYSQL迁到ORACLE的需求,应用程序也要相应做一些修改.本人总结出以下几点注意事项,希望对大家有所帮助. 1. 自动增

如何在oracle的blob字段里保存多个文件

Oracle的BLOB字段类型可以用来保存长2进制数据.但是通常读写BLOB字段数据的代码都是很罗嗦,非细心编码很容易出错.我把这个功能集成到我的OCI包装库(ORADBI)中.下面的例子就是演示如何使用ORADBI把多个文件按保存到一个字段里. 我在另外的例子中将演示如何把BLOB字段中的数据还原为文件. 整个ORADBI是我在OCI基础上写的C语言API.从创作这个API到一直不断的更新维护,已经有1年多了.我也将一直维护下去,不断完善和添加新的功能.ORADBI是完全免费和完全开源的,使用