问题出现:
最近在做mysql数据导入到hive多分区表的工作。在测试时发现hive数据总条数多出源表数据几倍。从mysql查看几条数据与hive对应的数据进行对比,发现mysql一条数据在hive中被加载成多行数据。如下图:
原始description_shop一条数据:
😊😊😊 Bem-vindos a minha loja! 😊😊😊
📢📢 Oferecemos a você os melhores produtos e artigos para sua casa!
🌟🌟 Nossa missão é atender você da melhor maneira, não se esqueça de nos avaliar com 5 estrelas!
🎈🎈 Siga nossa loja e receba um cupom adicional!
💕💕 Boas compras!
mysql中取10条数据结果:
hive中取10条数据结果:
问题出现了,mysql中1条数据在hive中被加载成了多行。
有同学第一时间可能想到我的sqoop语句中是否将-m 指定为1,来,下面上测试脚本:
#1.建hive分区表,先将分区表建好
#2.修改需要导入的表和批次
tablename='shopinfo1'
#3.一级分区
locate='test'
#4.二级分区
batch='1'
#5.将mysql数据导入到hdfs中
sqoop import --connect "jdbc:mysql://192.168.0.213:3306/test" --username root --password 111111 --table $tablename --target-dir /user/hive/warehouse/shopinfo1/locate=$locate/batch=$batch --append --fields-terminated-by '\t' -m 1
#6.增加hive分区表及指定数据目录
#7.刷新分区表
hive -e 'ALTER TABLE shopinfo1 ADD PARTITION(locate="'$locate'",batch="'$batch'") LOCATION "'/user/hive/warehouse/shopinfo1/locate=$locate/batch=$batch'";'
很明显,我已经指定了 -m 1,即指定执行MapReduce的个数为1。
解决方案:
1.使用parquet存储方式。
将hive分区表改成以parquet方式存储数据,同时在利用Sqoop导入数据的时候也要指定parquet存储方式。
过程:
#5.将mysql数据导入到hdfs中
sqoop import --connect "jdbc:mysql://192.168.0.213:3306/test" --username root --password 111111 --table $tablename --target-dir /user/hive/warehouse/shopinfo1/locate=$locate/batch=$batch --append --fields-terminated-by '\t' -m 1 --as-parquetfile
HDFS上数据:
2.利用优化参数–direct
sqoop参数中有优化mysql导数速度的关键参数–direct。
该参数的作用是利用直连模式,使用mysqldump加快速度。
但是使用该参数需要注意以下问题:
- 【WARN manager.DirectMySQLManager: Direct-mode import from MySQL does not support column】direct方式仅仅支持所有的列 有column的话direct就无效了
- 【Error: java.io.IOException: Cannot run program “mysqldump”: error=2, No such file or directory】 需要把mysqldump复制到从节点:scp /usr/bin/mysqldump cm-slave1:/usr/bin/
- 使用direct会使得–null-non-string –null-string无效
过程:
#5.将mysql数据导入到hdfs中
sqoop import --connect "jdbc:mysql://192.168.0.213:3306/test" --username root --password 111111 --table $tablename --target-dir /user/hive/warehouse/shopinfo1/locate=$locate/batch=$batch --append --fields-terminated-by '\t' -m 1 --direct
HDFS上数据:
两种方案的MR区别:
1.改用parquet存储方式的MR过程是Map阶段读取了每条数据
2.添加–direct参数的MR过程Map阶段一次性读取全部数据
展示解决后的效果:
1.使用parquet方式
2.使用–direct方式
总结,mysql数据的编码格式是utf8mb4,hive编码格式utf8.不管用parquet存储还是–direct参数优化,都不能将emoji表情数据完整的存储。
如果有同学有更好的处理方式,希望不吝赐教🌹🌹🌹