数据迁移心得

  前几天出差,去客户现场帮忙迁移数据,经过几天的奋战,终于将迁移数据自动化起来,并且可以日跑批操作,这里小编就跟大家分享下,这其中踩过的坑(也可能是实战经验不丰富导致)。
  首先,荣小编我抱怨一下,不是自己熟悉的开发环境真的有些难过,给一台电脑,咱不说没有IDE,就连java都没有安装,连接数据库的工具也没有,唯一值得庆幸的是有xshell,但是完全不符合个人快捷键的喜好,没办法,想要开发高效,自己动手配置吧。单单是配置这些开发环境就整整牺牲了小编一上午的时间,还好后期开发有明显的提速。中午吃个饭,下午进入正题。
  下午拿到迁移任务,发现一个库中有很多表,其中表有大有小,当时我沉默了几秒钟,感觉这个星期是交代在这里了。这里小编在那几秒钟的沉默中也把这个迁移流程想了一下,首先数据是存在关系型数据库中的,然后我们要通过sqoop将数据上传到HDFS中,然后用hive的外表去映射这些数据,最终建立有索引的内表来存储一份完整的数据。内表一般都是分区,分桶,且有索引的orc表,查询速度明显比外表快很多。那么接下来小编就将这其中的步骤,一点点的分析下。

前期准备:

   拿到一个库的数据时,我们首先分析下这里有哪些表比较大,哪些表比较小,将大表和小表分开,使用不同的迁移方法,一般都是客户提供每张表的数据条数,如果没有的话,只能selecct count(*) from table; 将这些表的数据查出来,不仅便于区分大小表,而且对后期数据核对有较大的帮助。

1. 从关系型数据库将数据迁移到HDFS中

  这里迁移数据小编是用的sqoop,虽然sqoop比较慢,但是学习成本相对较低,而且便于批量的生成语句,对开发要求没那么高。首先先测试一个sqoop是否可以成功的迁移数据,然后编写脚本批量的生成sqoop语句,最后调用这些语句,后台并行的迁移数据。这里小编先说说使用sqoop的几个小窍门:

  • 如果集群的资源比较充分,一般新集群是没有什么生产任务的,我们的sqoop语句中可以加入:

    -m 这个参数可以设置为>1 ,表示并行多个map去抽取数据。
    --split-by 当然-m 参数设置大于后,要同时设置这个参数,表示以表中的哪一个字段去分map并行。

    这里选取--split-by 尽量使用表中比较分散的字段,保证每一个map任务抽取的数据量都大致相同。

  • 如果表的数据量比较大,比如超过亿条,我们这里就需要将这个表分成多个sqoop去抽取:

    --query : 指定where后的条件,抽取部分数据
       这样的好处是:如果只有一个sqoop任务,抽取了90%的数据后,发现sqoop任务挂了,那么本次抽取失败,不仅耗时,而且数据没有抽取到。分多个sqoop任务,不仅可并行,而且每个任务的数据量也不大,如果有任务挂了,只需要抽象抽取那个where条件下的数据即,并且对于找错也有极大的帮助。
       分区字段的选取也同样重要,这里一般都是使用日期作为where的后的条件,保证每个sqoop任务分的的数据量相差无几。

    • sqoop抽取数据的目录规划

      #小表目录规划
      /tmp/库名/表名
      #大表的目录规划
      /tmp/库名/表名/分区名
  • query语句:在sqoop命令中,我们编写查询语句去抽取数据时,切记不要:

    -- ×
    select * from table;
    -- √
    select 字段1,字段2.... from table;
    不然可能会导致sqoop抽取速度变慢,甚至可能导致没有抽取到数据。
       当我们注意了以上的内容后,就可以编写脚本批量的生成每张表的sqoop语句了,根据库名.表名,获取关系型数据库中表的元数据,最后将sqoop组装起来。最后在编写任务脚本,定时执行这些sqoop语句。
    实际数据分享:
       这里小编测试过,数据量比较大时,多sqoop和单sqoop的耗时:
    以600G数据为例:
       - 多sqoop 并行抽取数据耗时:3~4小时。
       - 单sqoop 抽取数据耗时:12小时以上。
       - 单sqoop && (-m 1)抽取5千万条数据,大概是27分钟。

2. 建立外表映射

   说白了就是将抽取到的数据,在hive中通过外表的方式映射出来,其实这里没什么难的,主要是看客户如果要求,可能是外表单独一个库,或者外表的名称统一是:表名_ext。但是切记,不要手动的去编写建表语句,如果表有百张以上,心态容易炸,这里可以使用关系型数据库的元数据 ,生成hive的建表语句的,这里我们与MySQL为例:

SELECT CONCAT(‘create table ‘, TABLE_NAME, ‘(‘, substring(column_info, 1, length(column_info) - 1), ‘)‘, ‘ comment ‘, ‘"‘, TABLE_COMMENT, ‘"‘, ‘;‘)
FROM (SELECT TABLE_NAME, TABLE_COMMENT, group_concat(CONCAT(COLUMN_NAME, ‘ ‘, DATA_TYPE, ‘ comment ‘, ‘"‘, COLUMN_COMMENT, ‘"‘)) AS column_info
FROM (SELECT t1.TABLE_NAME, CASE WHEN t2.TABLE_COMMENT = NULL THEN t1.TABLE_NAME ELSE t2.TABLE_COMMENT END AS TABLE_COMMENT, COLUMN_NAME, CASE WHEN DATA_TYPE = ‘varchar‘ THEN ‘string‘ WHEN DATA_TYPE = ‘int‘ THEN ‘int‘ WHEN DATA_TYPE = ‘tinyint‘ THEN ‘tinyint‘ WHEN DATA_TYPE = ‘decimal‘ THEN ‘double‘ WHEN DATA_TYPE = ‘datetime‘ THEN ‘string‘ WHEN DATA_TYPE = ‘timestamp‘ THEN ‘string‘ WHEN DATA_TYPE = ‘float‘ THEN ‘double‘ WHEN DATA_TYPE = ‘double‘ THEN ‘double‘ WHEN DATA_TYPE = ‘bigint‘ THEN ‘bigint‘ END AS DATA_TYPE, CASE WHEN COLUMN_COMMENT = NULL THEN COLUMN_NAME ELSE COLUMN_COMMENT END AS COLUMN_COMMENT
FROM COLUMNS t1 JOIN TABLES t2 ON t1.TABLE_NAME = t2.TABLE_NAME
WHERE t1.TABLE_NAME = ‘t_app_equipment_status‘
) t3
GROUP BY TABLE_NAME, TABLE_COMMENT
) t4;

网上这样的例子很多,这里小编就不在介绍。当外表建立好之后,最好核对一下数据量的大小,对比下关系型数据库中表的数据和hive中的数据是否相同,这样验证了sqoop这一环节是否有数据丢失的情况。
遇到的坑:
  当大表我们在分区抽取时,是无法直接映射成为外表的,我们需要建立范围分区表,将表的分区目录映射到各个分区上。

3. 建立高效的内表

   其实这一步就是将,外表的数据,insert到一张和外表字段相同的经过优化的内表中,这张内表一般都是分区分桶,建立索引,或者基于闪存的表,反正就是查询的速度大大提高的一张表,也叫做业务表。
   小编这里用的是一种基于闪存的高效查询的,企业内部开发的一种表结构。小编这里介绍一下如何确定分桶字段:分桶的好处是
   (1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
   (2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。
   那么如果确定分桶字段呢,一般的如果有主键的表就使用主键作为分桶字段,如果没有主键的表,找几个比较分散的字段使用:

 select count(distinct feild) from table;

找出数据最大的那个字段作为分桶字段。具体的分桶数,这里建议是一个质数,因为如果是一个非质数,那么可能导致分桶不均匀,因为如果分桶数是9的话,那么字段值如果为18、27都会分到一个桶中,可能会导致桶“热点”。

4. 外表insert 到 内表中

   这个过程是耗时仅次于sqoop的过程,由于我们的内表建立的分区,那么在这个步骤中我们需要使用hive的动态分区插入,插入语句一般都是:

    insert into table_1 partition(par_field) select field1.field2...from table_2 ;

这里需要注意的是select 最后一个字段一定要是分区字段。
   当我们insert 后,需要核对下是否所有的数据全部insert成功,此时:外表数据量=内表数据量=关系型数据库数据量

5. 日增量数据的处理

   当我们完成数据迁移后,其实外表相当于一个中转站,仅仅是将数据中转到内表中,如果我们确保了内表中有一份完整的数据,此时可以将外表的数据清空,这也是为什么我们将外表的location 设置为/tmp下 的原因,清空外表数据后,将日增数据抽取到外表的location地址上,然后全量的将外表数据insert到内表中,就保证了日增量数据的成功导入到hive。

原文地址:https://blog.51cto.com/14048416/2425833

时间: 2024-11-06 07:10:49

数据迁移心得的相关文章

关于数据迁移的方法、步骤和心得

在项目中经常会遇到系统完全更换后的历史数据迁移问题,以示对客户历史工作的尊重,何况很多数据仍有保留的必要. 那怎么做历史数据迁移呢? 系统分析: 1.分析原有的业务系统 精确到大致的系统功能模块.大致的处理流程即可 2.分析现有的业务系统 精确到大致的系统功能模块.大致的处理流程即可 3.分析两者自己的区别和差异 大致分析一下两个业务系统之间的区别,有助于确定工作量和工作进度 4.分析用户对旧有数据的需求 分析对旧有数据的需求,才不至于盲目的全部性的进行迁移 5.分析用户对旧有数据的处理规则 旧

使用SSIS对Dynamics CRM 系统进行数据迁移

嗨,各位.最近项目一直都很忙,并且自己也一直在思考职业发展的问题,所以有很长一段时间没静下心写几篇Blog了.最近我参与的项目是Dynamics CRM 2011 到 Dynamics CRM 2013 Online的数据迁移,刚好接着今天这个机会和大家分析一下数据迁移的心得吧. 读过我之前文章的朋友肯定记得我把Dynamics CRM的接口分为了两大类:1)功能接口,2)数据接口.今天要说的数据迁移可以理解为数据接口,实现数据接口的方式有很多种,比如C#制作的程序,数据库层的SQL 脚本,以及

数据迁移经验总结——亿级别多表异构的数据迁移工作

由于系统改版,最近三个月在做数据迁移工作,由于业务的特殊,基本将数据迁移所能踩的坑都踩了一遍,决定好好做个总结. 迁移类型--新老系统表结构变化较大的历史数据 一.核心问题 1.新老表结构变化极大.新表是以deliver为核心,另外还涉及仓储系统的一张表,订单系统的4张表,并按照新的逻辑映射关系进行迁移. 2.增量数据迁移.在全量数据迁移时必然会有新的数据,这些数据应该实时进行迁移 3.亿级别数据性能.效率的考虑.由于订单业务非常重要,数据迁移带来的qps对数据库的压力非常大,需要不断测试迭代找

oracle 数据库数据迁移解决方案

大部分系统由于平台和版本的原因,做的是逻辑迁移,少部分做的是物理迁移,接下来把心得与大家分享一下 去年年底做了不少系统的数据迁移,大部分系统由于平台和版本的原因,做的是逻辑迁移,少部分做的是物理迁移,有一些心得体会,与大家分享. 首先说说迁移流程,在迁移之前,写好方案,特别是实施的方案步骤一定要写清楚,然后进行完整的测试.我们在迁移时,有的系统测试了四五次,通过测试来完善方案和流程. 针对物理迁移,也即通过RMAN备份来进行还原并应用归档的方式(这里不讨论通过dd方式进行的冷迁移),虽然注意的是

MySQL数据迁移问题

最近尝试了一下小型数据迁移.本地迁移,windows平台,修改配置文件中的data_dir项,然后将旧的data文件下的数据文件全部拷贝过去. 之后登陆数据库,竟然1145错误.可以看到数据库的结构,各个表的名称,但是想深入表看其中数据却看不了. 不知道为什么,搜了一下,有人说拷贝的时候原SQL服务没有停下,有的说InnoDB引擎创建的表不支持这种直接拷贝,而MyISAM则可以. 没办法,只能采取笨办法咯~先在原来数据库上进行备份,然后再导入. mysqldump -u root -p data

Code First Migrations更新数据库结构(数据迁移) 【转】

背景 code first起初当修改model后,要持久化至数据库中时,总要把原数据库给删除掉再创建(DropCreateDatabaseIfModelChanges),此时就会产生一个问题,当我们的旧数据库中包含一些测试数据时,当持久化更新后,原数据将全部丢失,故我们可以引入EF的数据迁移功能来完成. 要求 已安装NuGet 过程示例 [csharp] view plaincopyprint? //原model //原model [csharp] view plaincopyprint? us

数据迁移,iis的各种坑

最近在搞iis发布  本来在家里实验过很多次 都是可以的 觉得很容易!但是到客户现场去试的时候发现各种坑 在这里给大家说说  望大家注意点哈! 首先:数据迁移先是备份数据库,然后再还原  这个地方一定要注意数据库版本问题,比如你如果在sqlserver2012上备份的,到sqlserver2008版本上还原就不行,因为这是高版本还原到低版本了 就不兼容,但是低版本还原到高版本就可以! 第二步:还原好了数据库,vs代码要配置服务器了,也要注意个问题:因为vs配置的是sqlserver的sql认证账

EF数据迁移,未将对象引用设置到对象实例

现象: 执行Enable-Migrations -force时就报"未将对象引用设置到对象实例"的异常: DbProviderServicesExtensions.GetProviderManifestTokenChecked 原因: 1.项目启动项的App.config或web.config里面没有配置 entityFramework节点或connectionStrings节点,EF在数据迁移时找不到数据库连接串信息 2.项目启动项配置错误,应该选择有entityFramework节

SQL SERVER几种数据迁移/导出导入的实践

SQLServer提供了多种数据导出导入的工具和方法,在此,分享我实践的经验(只涉及数据库与Excel.数据库与文本文件.数据库与数据库之间的导出导入). (一)数据库与Excel 方法1: 使用数据库客户端(SSMS)的界面工具.右键选择要导出数据的数据库,选择“任务”——“导出数据”,下图1,按照向导一步一步操作即可.而导入则相反,导入时,SQLServer会默认创建一张新表,字段名也默认跟导入的Excel标题一样,并且会默认字段数据类型等.当然在可以在向导进行修改.需要注意的是如果标题不是