oracle insert的扩展

本文详细介绍了如何利用Oracle的向表发散弹枪技术,包括插入单个表、多个表的方法及注意事项。通过实际案例演示了如何灵活运用这些技术,提高数据库操作效率。

 

 

    向一个表发散弹枪

 

          ⑴ insert into table_name [(column[,column...])] select_statement
             每次只能插入一个表,但性能上比写多条insert语句要高。另外,oracle还提供create table table_name as select ...,as不可少!实现直接创建并且插入表,依赖于后面的select语句的结果,如:create table new_table as select * from source_table where 1=0
             案例:
             表mxt新增一列time,那么这个列会被置在最后,现想把此列放于第2
             create table copy_mxt as select id,time,name from mxt;
             drop table mxt;
             rname copy_mxt to mxt;

 

    向多个表发散弹枪

 

          类型:
            ① 无条件的insert
            ② 带条件的insert all
            ③ 带条件的insert first
            ④ pivoting insert


          多表insert的使用限制:
            ① 只能对table使用insert,不能对视图或物化视图使用
            ② 不能对远程表使用这个插入操作
            ③ 多表插入时,不能指定一个表的集操作
            ④ 多表insert的into的目标表加在一起的列数不能超过999

 

          ㈠ 无条件的insert
             语法:
             insert all
             into dest_table1 [column(,column...)] [values (...)]
             into dest_table2 [column(,column...)] [values (...)]
             ...
             select_statement  --values中指定是select结果列,如果没有values指定列,那么表示目标表的列类型和顺序与select语句查询的结果完全一致。建议不要省略目标表中的列和values,增强可读性。
             例子:

create table emp_1 as select employee_id,last_name from employees where 1=0;
create table emp_2 as select * from employees where 1=0;
create table emp_3 as select * from employees where 1=0;
insert all
--不指定emp_1后面的列,也没有values指定列,那么emp_1所有列类型和顺序与查询的列的类型和顺序一致
--也就是emp_1中只有查询结果中的那几列,而且类型和顺序一致
  into emp_1
--指定了emp_2后面的列,但没有values指定列,表示emp_2中要插入的列被选择出来,与查询结果列的类型和顺序一致
--emp_2也有很多列,不止这两列
  into emp_2(employee_id,last_name)
--指定emp_3后面的列和values指定列,那么values后面的列名必须与查询结果一致,如果查询有别名,必须在values中使用别名
--emp_3指定的列的类型和顺序必须与values保持一致
--emp_3也可能列数大于指定列数
  into emp_3(employee_id,last_name) values(e_id,e_last_name)
  select employee_id e_id,last_name e_last_name 
   from employees


 

          ㈡ 带条件的insert
             包括:insert all和insert first
             语法:
             insert all
             when condition_statement
             then into dest_table1[指定列] values[查询中的列]
             when condition_statement
             then into dest_table2[指定列] values[查询中的列]
             select_statement
             注释:带条件的insert all与insert first的区别在于只按条件对查询的结果进行刷选,不会考虑前面已经匹配过的记录,每次都是全量匹配,而insert first对已经匹配过的记录不予考虑,下一个when会自动过滤掉上一个匹配过的行记录
             例子:

insert all
  --将查询结果s_id>20的插入,条件中指定的列必须与查询结果名字一致,如果有别名,请用别名
  when e_id>20
    then into emp_1
  --s_last_name为M开头的插入,可能插入的行与s_id有重复
  when e_last_name like 'M%'
    then into emp_2(employee_id,last_name)
  --如果指定else,则不满足上面条件的插入到emp_3,插入的行不会与上面两个重复
  else
    into emp_3(employee_id,last_name) values(e_id,e_last_name)
  select employee_id e_id,last_name e_last_name
    from employees


          ㈢ pivoting insert(旋转插入)
             关系型数据库三范式,归纳起来三句话:
             ① 行不可再分
             ② 列不可再分
             ③ 列不可重复
             但很多情况下,范式都会被破坏。使用旋转插入可以实现将非关系表记录转换为关系表在数据库存储。和insert all类似,不过这里是向一个表发散弹枪,将列转变成行。
             例子:

create table sales (year_2008 number,year_2009 number,year_2010 number,year_2011 number,year_2012 number)
insert into sales values(191,922,392,942,592)
select * from sales

create table cow_sales(year_sales number)

insert all
  into cow_sales values(year_2008)
  into cow_sales values(year_2009)
  into cow_sales values(year_2010)
  into cow_sales values(year_2011)
  into cow_sales values(year_2012)
  select * from sales

select * from cow_sales


 

### OracleINSERT INTO 操作引发物理读的现象及原因 在 Oracle 数据库中,`INSERT INTO` 操作可能引起较高的物理读现象,这通常与数据块的访问模式以及索引维护有关。以下是具体分析: #### 物理读高的主要原因 1. **索引的影响** 当向表中插入新记录时,如果该表存在索引,则每次插入都会触发索引更新操作。这种更新可能导致大量的随机 I/O 操作,尤其是当索引树需要重新平衡或者扩展时。随着表中的数据量增大,索引的高度也会增加,从而进一步加剧了 `db file sequential read` 的等待时间[^2]。 2. **缓冲区缓存未命中** 如果目标表的数据块尚未加载到内存(即数据库高速缓存区),则必须从磁盘上读取这些数据块以完成插入操作。这种情况下的物理读是不可避免的,尤其是在大规模批量插入场景下[^1]。 3. **保持池(Keep Pool)的作用有限** 虽然可以利用 Oracle 的 Keep 缓冲池来提高热点对象的缓存效率,但如果插入操作涉及的对象超出了 Keep Pool 的容量限制,仍然会发生缓存淘汰行为。这意味着某些频繁使用的数据页可能会被移除出缓存,进而导致后续再次访问时发生额外的物理读。 4. **顺序写入 vs 随机读取** 插入操作本质上属于顺序写入过程,但由于伴随有大量随机性质的索引节点查找活动,因此整体性能表现更接近于混合型 IO 工作负载。特别是对于具有复杂多层结构的大规模 B*Tree 类型索引而言更是如此[^3]。 #### 解决方法 针对上述提到的各种因素,可以通过以下几种方式尝试降低由 `INSERT INTO` 所带来的过高物理读开销: - **调整存储参数** 合理设置表空间及其对应文件的增长策略,确保有足够的连续可用空间供新增加的数据占用;同时考虑采用更大的初始分配单元大小(EXTENT SIZE),减少因频繁申请小片断而导致碎片化问题的发生几率。 - **优化索引设计** 对现有索引进行全面审查,删除那些利用率较低甚至完全没有必要的辅助索引项;另外还可以探索分区技术的应用可能性,在不影响业务逻辑的前提下按需拆分大表成多个子集以便更好地管理其内部组织形式并提升局部区域内的检索速度。 - **预热缓存机制** 提前将预计会被高频度访问的目标范围内的全部内容主动载入共享全局区内存当中去,以此尽可能规避未来可能出现的新一轮冷启动效应所造成的延迟影响。 - **并发控制措施** 控制同一时间段内允许执行此类耗资源密集型任务的最大数量上限值,并通过排队调度算法合理安排各请求之间的先后顺序关系,防止过度竞争公共资源而造成系统过载崩溃风险。 ```sql -- 示例:创建覆盖索引来替代原有单列索引 CREATE INDEX idx_covering ON tb_real_time_car(col_a, col_b); ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值