在ORACLE里用存储过程定期分割表
baidu
Oracle数据库里存放着各种各样的数据,其中有一些数据表会随着时间的推移,越来越大。如交友聊天的日志、短信收发的日志、生产系统的日志、动态网站发布系统的日志等等。这样的信息又和时间紧密相关,有没有办法让这些日志表能按时间自动分割成历史年月(如log200308,log200309)的表呢? 请看看我用存储过程定期分割表的方法吧。
一、问题的引出
1.初学数据库时只知道用delete来删除表里的数据。但在Oracle数据库里,大量delete记录后,并不能释放表所占用的物理空间,这里面有一个高水位的概念,所以我们不能用delete来分割表。
2.用重命名(rename)表的方法
(1) 先建一个和原来日志表(假如是log)数据结构一模一样的新表(如log_new),建约束、索引及指定字段的默认值;
(2) 重命名表log到log_YYYYMM;
要注意的问题是OLTP系统可能会因为DML操作阻碍重命名执行成功,出现ORA-00054资源正忙的错误提示,需要试多次才能成功。
(3) 重命名表log_new到log。
这样应用程序不用修改(受影响的时间仅几秒钟),日志表就被截断分割了。
上述步骤可以在Oracle里用存储过程来实现。
二、用存储过程来分割表
可以看到在重命名表的方法中,步骤(2)是个关键。下面这个rename_table过程会在有锁阻碍的情况下用递归的方式重试100次。
重命名原始表到目标表的存储过程rename_table:
create or replace procedure rename_table
(source_name in varchar2,
target_name in varchar2,
times in out number)
is
query_str varchar2(4000);
source_name1 varchar2(64);
target_name1 varchar2(64);
cursor c1 is select segment_name from user_segments
where segment_name=upper(source_name);
dummy c1%rowtype;
cursor c2 is select segment_name from user_segments
where segment_name=upper(target_name);
dummy2 c2%rowtype;
begin
source_name1:=source_name;
target_name1:=target_name;
open c1;
fetch c1 into dummy;
-- if c1%found then
-- dbms_output.put_line(source_name1||'exist!');
-- end if;
open c2;
fetch c2 into dummy2;
-- if c2%notfound then
-- dbms_output.put_line(target_name1||'not exist!');
-- end if;
if c2%notfound and c1%found then
query_str :='alter table '||source_name1||' rename to '
||target_name1;
execute immediate query_str;
dbms_output.put_line('rename success!');
end if;
close c1;
close c2;
exception
WHEN OTHERS THEN
times:=times+1;
if times<100 then
-- dbms_output.put_line('times:'||times);
rename_table(source_name1,target_name1,times);
else
dbms_output.put_line(SQLERRM);
dbms_output.put_line('error over 100 times,exit');
end if;
end;
/
截断分割log表的存储过程log_history:
create or replace procedure log_history
is
query_str varchar2(32767);
year_month varchar2(8);
times number;
begin
select to_char(sysdate-15,'YYYYMMDD') into year_month from dual;
times:=0;
query_str :='create table log_new pctfree 10 pctused 80
as select * from log where 1=2';
execute immediate query_str;
query_str :='alter table log_new add constraints log_'
||year_month||'_pk
primary key (id) tablespace indx nologging pctfree 10';
execute immediate query_str;
query_str :='alter table log_his modify logtime default sysdate';
execute immediate query_str;
query_str :='create index log_'||year_month||'_logtime on log(logtime)
tablespace indx nologging pctfree 10';
execute immediate query_str;
rename_table('log','log'||year_month,times);
query_str :='alter table log_new rename to log';
execute immediate query_str;
end;
/
当然您工作环境的日志表可能和我这个做例子的日志表结构上有所不同,约束条件、索引和默认值都不尽相同。只要稍加修改就可以了。
三、用户需要有create any table系统权限(不是角色里包含的权限)
因为在执行存储过程时,由角色赋予的权限会失效, 所以执行log_history的用户一定要有DBA单独赋予的create any table系统权限。
最后在OS里定时每月一号凌晨0:00分执行log_history,让存储过程定期分割表。
如果要分割的日志表很多,模仿log_history可以写很多类似的存储过程来分割不同项目里的日志表。然后让OS按月,按周或者不定期的执行这些存储过程, 管理员只要查看日志就可以了。
四、其它注意事项
如果应用程序有BUG,可能对在用原始日志表产生长期不能释放的锁,执行log_history重命名会不成功。
这时DBA可以查看数据字典:
select object_id,session_id,locked_mode from v$locked_object;
select t2.username,t2.sid,t2.serial#,t2.logon_time
from v$locked_object t1,v$session t2
where t1.session_id=t2.sid order by t2.logon_time;
如果有长期出现的一模一样的列(包括登录时间),可能是没有释放的锁。
我们要在执行分割日志表的存储过程前,用下面SQL语句杀掉长期没有释放非正常的锁:
alter system kill session 'sid,serial#';
五、结束语
用上面介绍的存储过程定期分割日志表有很大的灵活性。历史数据不仅查询方便,转移和备份起来也都很容易。Unix和Windows平台的都可以使用。对服务器硬盘空间较小的中小型公司意义尤其明显。
分享到:
相关推荐
总结来说,通过在Oracle数据库中使用存储过程定期分割表,可以有效地管理不断增长的时间相关数据,优化数据库性能,便于数据管理和归档。通过创建并调用适当的存储过程,这一过程可以自动化,确保了数据库系统的稳定...
数据仓库建模技术.pdf 在数据库中实现base64编码和解码.doc 触发器使用教程和命名规范.doc TransactSQL.doc Schema常用脚本.doc rsultset.doc oracle傻瓜手册 ORACLE 中存储过程定期分割表.doc ORACLE 物理文件大小...
根据提供的标题、描述、标签及部分内容,我们可以了解到这项工作主要关注的是如何将Oracle数据库中的分区表数据定期迁移到另一个数据库,并且对整个过程进行了详细的技术规划。以下是对这些信息进行整理后得到的关键...
表空间是Oracle数据库中的逻辑存储单元,它将数据组织成可管理的部分,允许数据库管理员更好地控制数据存储和性能。表空间可以包含多个数据文件(Data Files),每个数据文件在物理磁盘上占据一定的空间。 - **表...
### Oracle存储空间管理及应用方案 #### 摘要与引言 本文旨在全面解析Oracle数据库的存储架构及其管理机制,特别关注表空间、回滚段、临时表等关键组件的作用与管理策略,并针对实践中可能遇到的问题进行深入探讨...
- **定义**:视图是一种虚拟表,其内容是由存储在一个表或多个表(或其它视图)中的数据构成。 - **优点**:简化查询、提供安全性、数据抽象化等。 ### 四、Oracle管理与优化 #### 4.1 性能监控与诊断工具 - **AWR...
- **存储过程**:预编译的SQL和PL/SQL代码集合,可以在数据库服务器上执行。 - 参数传递:可以使用IN、OUT或IN OUT参数传递值。 - 调用方式:通过PL/SQL或应用程序调用存储过程。 - **触发器**:当特定事件(如...
- **段(Segment)**:是在表空间内分配的一组连续的空间,用于存储特定类型的数据(如索引、表等)。 - **区(Extent)**:是由连续的数据块组成的存储区域,是分配给段的基本单位。 - **数据块(Block)**:是数据库中...
Oracle 11g R2引入了多租户架构,允许在一个数据库实例中创建多个可插拔数据库(PDB),每个PDB都拥有独立的用户、表空间和资源限制,但共享相同的物理存储和管理资源。这种架构有助于简化管理、提高资源利用率、...
2. **分区技术**:通过分区技术可以将大型表分割成更小的部分,这样在查询时只需要扫描相关的分区,而无需扫描整个表,从而提高查询效率。 3. **并行查询**:利用Oracle的并行查询功能可以让多个进程同时执行查询的...
2. **索引组织表**:数据按索引顺序存储,适用于频繁使用索引查找的情况。 3. **数据压缩**:通过压缩技术减少存储空间的需求,同时保持较高的数据读取速度。 4. **实时应用集群**:提供高可用性和负载均衡功能,...
- **表空间:** 表空间是Oracle数据库中的逻辑存储单元,一个数据库可以包含多个表空间。 - **文件:** 每个表空间由一个或多个数据文件组成,数据文件是表空间在物理磁盘上的存储形式。 - **§1.3.2 实例** - **...
通过定期运行像`BB`这样的存储过程,可以确保分区结构始终与业务需求保持同步,从而优化查询性能。 通过以上分析,我们可以看出Oracle的自动分区功能如何通过存储过程和动态SQL实现智能化的数据管理,以适应不断...
- **中文字段名读取**:利用Oracle的视图读取中文字段名,并使用相同的方法将结果连接后再分割,存储于数组中。 #### 四、检索算法 检索时,系统应对综合信息字段执行检索,随后对结果进行过滤,确保只有与关键字...
### Oracle Concepts 中文版知识点概览...通过以上内容的详细介绍,我们可以看出Oracle数据库不仅在数据管理和存储方面有着强大的功能,而且在应用程序开发方面也提供了广泛的支持。这对于开发者来说是非常宝贵的资源。
7. **安全性与最佳实践**:在处理FTP和数据库操作时,应确保遵循安全最佳实践,如使用安全连接、限制权限、加密传输和存储敏感数据,以及定期备份。 8. **性能优化**:对于大量数据导入,可能需要考虑性能优化策略...
表空间是Oracle存储数据的基本单位,合理规划表空间可以避免存储瓶颈。创建多个数据文件分散在不同磁盘上,可以提高I/O性能。根据业务需求,可以选择本地管理表空间(LMT)或字典管理表空间(DMT),前者简化了空间...
通过充分利用Oracle的查询优化技术,如索引、查询重写、物化视图、并行查询、分区以及存储过程和函数的优化,可以显著提升前台实时查询的响应速度和后台大数据量统计的速度。这些策略的应用需要根据具体场景灵活调整...