今天有个同学问我一个问题,也是一个实际的案例,我简单分析了一下,发现还是有很多可以考究的地方。仅做参考。
问题是,系统里目前有一个大表,因为历史数据的沉淀,目前有60多亿的数据,不是分区表,现在得到反馈说insert的操作比较满,想优化一下,同时把部分历史数据需要做一些清理。
对于这类操作,要求停机时间尽可能短,有什么好的办法。
对于这个问题看起来问题似乎是很明显的。
目前反应出的问题是Insert慢,可能有下面的几个原因。
1.表索引巨大,索引维护管理要复杂一些
2.表中可能含有一些冗余索引,或者多个索引。
3.insert操作可能也是误导,很有可能是查询更慢。
对于这类问题还是需要琢磨一下。简单做了确认,查询其实也很慢。
那么问题的原因可以再补充几个。
4.sql语句导致的性能问题
5.高水位线导致的问题
整个问题的改进思路可以大体描述为下面的情况。
需要把表改为分区表,建立分区索引
表中的数据需要做清理,只保留部分的数据,比如按照50%的比例。
如果是这样的情况,很自然的就想到了在线重定义,不过在线重定义在使用的时候,分区肯定是可以的,能够保证在线,但是性能上还是会差一些,毕竟需要内部去同步一遍数据。
数据清理的部分还是不好做,还得进一步清理。
如果使用exp/imp或者expdp/impdp的时候,除了工具本身的效率外,还有一个部分就是对于导入数据都基本是串行,如果一个分区表有100个分区,那么100个分区都会同时持有锁。
如果使用sqlldr来做,都可以实现,不过主要的问题不在分区上了,而是在于历史数据清理,都需要先同步导入再进一步清理
同时分区表还需要创建所有匹配的分区,然后导入数据之后再清理分区。
画图来说明就是下面的形式。
首先抽取的时候是按照时间分区来抽取生成相应的dump文件,比如分区是2013-01-01的可以根据ext_date来抽取,得到相应的外部表dump
其它的时间段都是类似的处理,那么导出这些“分区”数据之后,在导入的时候就可以并行+并发来做了。可以对每个分区单独开启一个导入的处理进程,对每一个处理进程可以开启并行来处理。
而且一个重要的地方就是,如果2013年的分区不需要,那么我就压根不导入。
当然这个过程还是需要窗口时间,个人觉得还是尽快完成,在这个代价上应该比在线要好一些,毕竟在线重定义在大数据量的时候在线处理时间还是有些长了。
如果采用了外部表的备份方式,历史数据还可以保留这种可读的备份。
最后还有一些细节需要说明的是,分区表test算是一个重新建立的分区表,还是需要考虑在清除原来的test表时保留原表的ddl,权限,相关的同义词,对应的pl/sql(包,存储过程,函数等等)保证在重建的这个表还是能够保留原来的“味道”
其实这个部分,使用外部表也是一个思路,其实对于拆表,分表自己也有一些心得,在以前的数据迁移中也尝试了一部分,在dtcc上也做了分享,简单说明一下。
这几种方式都可以在一定程度上把表拆分成更小的粒度。能够尽可能全面的利用起来。
一个60亿数据表改分区表+数据清理的改进思路
时间: 2024-10-23 20:16:48
一个60亿数据表改分区表+数据清理的改进思路的相关文章
Excel表格中汇总多个数据表中的数据的方法
Excel表格中汇总多个数据表中的数据的方法 1.打开需要处理的工作簿,在这个工作簿中,"11月采购表"和"12月采购表"工作表包含需要合并的数据,如图1所示."合计"工作表用于放置进行合并计算后的数据,其结构如图2所示. 图1 需要合并的两张工作表 图2 "合计"工作表的结构 2.在"合计"工作表中单击选择放置合并计算结果的单元格区域中的第一个单元格,然后在功能区"数据&
批量将数据表中原有的数据稍微变更再插入本表中
问题描述 批量将数据表中原有的数据稍微变更再插入本表中 表A中有以下字段,A_id,A_user_id,A_func_code,现在表A中有以下数据 A_id A_user_id A_func_code 1 张三 111 2 张三 222 3 张三 333 现在要表A中再插入数据,数据要求 要求为A_user_id等于张三的再插入时张三变更为李四 A_id为 sequence,大致描述如此,实际数据中不止这几个字段,数据也不止三条 等于说就是把原表中的A_user_id的数据再插入到本表中,只是
MYSQL教程:检查数据表和修复数据表
数据库在运行中,会因为人为因素或一些不可抗力因素造成数据损坏.所以为了保护数据的安全和最小停机时间,我们需制定详细的备份/恢复计划,并定期对计划的有效性进行测试. 本章结合MySQL服务器的运行机制和所提供的工具,介绍如何进行数据库的备份.维护和修复. 以下是几点防范的措施: 制定一份数据库备份/恢复计划,并对计划进行仔细测试. 启动数据库服务器的二进制变更日志,该功能的系统开销很小(约为1%),我们没有理由不这样做. 定期检查数据表,防范于未燃. 定期对备份文件进行备份,以防备份文件失效. 把
MySQL中复制数据表中的数据到新表中的操作教程_Mysql
MySQL是不支持SELECT - INTO语法的,使用INSERT INTO - SELECT替代相同用法,下面我们我们这里简答分一下新表存在和不存在两种情况,具体使用不同的语句.1.新表不存在复制表结构即数据到新表 create table new_table select * from old_talbe; 这种方法会将old_table中所有的内容都拷贝过来,用这种方法需要注意,new_table中没有了old_table中的primary key,Extra,auto_incremen
mysql创建数据表与删除数据表
创建数据表利用 命令:create table <表名> ( <字段名1> <类型1> [,..<字段名n> <类型n>]); 语法:CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)] [table_options] [select_statement] 例 代码如下 复制代码 mysql> create table MyClass(
删除数据表和清空数据表的内容(保存表结构)的SHELL脚本
A,删除指定数据库的所有数据表 #!/bin/bash # 删除mysql中所有表 # 示例: # Usage: ./script user password dbnane # Usage: ./script user password dbnane server-ip # Usage: ./script user password dbnane mysql.nixcraft.in # --------------------------------------------------- MUS
用sqldatasource 控件返回access数据表中的数据为什么不是按access表的顺序返回的?
问题描述 如题? 解决方案 解决方案二:你指定了排序了没?解决方案三:应该是AccessDataSource吧???使用数据源连数据库时,有个Where选项试一下~解决方案四:哎,好像理解错意思了,我的意思是,用数据源控件,为什么返回来的数据与数据表中的顺序不一样?????解决方案五:orderby
php怎么把数据表中的数据导出到excel表中
先定义头部信息,表示输出一个excel.然后再以table的形式把数据库的信息循环的echo出来,就好了. 代码如下 复制代码 <?php header("Content-type:application/vnd.ms-excel"); header("Content-Disposition:filename=xls_region.xls"); $cfg_dbhost = 'localhost'; $cfg_dbname = 'testdb';
【SQL Sever】将SQL Sever中的一个数据表的数据导出为insert语句
例如:这SQL Sever中的一张数据表,想要将这张数据表中的数据 转化成一个一个的insert语句存储在txt的文档中,那么不论走到那里这个insert语句一执行,我们就能将这个数据表中的数据插入到另一个地方了. 1>在新建查询中,创建一个对象,这个对象就是用来产生这个对象的,名字叫proc_insert,我们可以创建多个不重名的对象,当然也可以删除这个对象. 1 create proc proc_insert (@tablename varchar(256)) 2 as 3 begin