Sqoop导出数据不全排查:Shell脚本统计Hive与SQL Server行数问询
解决Sqoop导出Hive到SQL Server的数据一致性校验问题
我之前也碰到过Sqoop偶尔漏导数据的情况,你的"行数校验+自动重导"方案很靠谱。下面详细说明如何在Shell脚本中实现这两个表的行数统计,以及完整的执行逻辑:
一、统计Hive表的行数
在Shell中可以通过Hive CLI或者Beeline来执行计数查询,提取结果数值:
方法1:使用Hive CLI(适合传统Hive部署)
直接通过hive命令执行count(*),然后过滤掉日志行,只保留最终的数值:
# 替换为你的Hive库名和表名 HIVE_DB="your_hive_database" HIVE_TABLE="your_hive_table" # 统计行数并赋值给变量 hive_count=$(hive -e "select count(*) from ${HIVE_DB}.${HIVE_TABLE};" | grep -v "WARN" | tail -n 1)
grep -v "WARN":过滤掉Hive输出的警告日志行tail -n 1:取最后一行的计数结果(前面的行可能是Hive的启动日志)
方法2:使用Beeline(适合HiveServer2部署,更推荐)
如果你的集群用HiveServer2,建议用Beeline连接,安全性和稳定性更好:
HIVE_JDBC_URL="jdbc:hive2://your_hive_server:10000" HIVE_USER="your_hive_username" hive_count=$(beeline -u "${HIVE_JDBC_URL}" -n "${HIVE_USER}" -e "select count(*) from ${HIVE_DB}.${HIVE_TABLE};" | grep -v "WARN" | grep -v "Connected" | tail -n 1)
grep -v "Connected":过滤掉Beeline的连接成功提示行
二、统计SQL Server表的行数
需要用到SQL Server官方的命令行工具sqlcmd(确保脚本执行服务器已经安装该工具),通过它执行计数查询并返回纯数值:
# 替换为你的SQL Server连接信息 SQLSERVER_HOST="your_sqlserver_host" SQLSERVER_PORT="1433" SQLSERVER_DB="your_sqlserver_database" SQLSERVER_TABLE="your_sqlserver_table" SQLSERVER_USER="your_sqlserver_username" SQLSERVER_PWD="your_sqlserver_password" # 统计行数并赋值给变量 sqlserver_count=$(sqlcmd -S "${SQLSERVER_HOST},${SQLSERVER_PORT}" -U "${SQLSERVER_USER}" -P "${SQLSERVER_PWD}" -d "${SQLSERVER_DB}" -Q "select count(*) from ${SQLSERVER_TABLE};" -h -1)
-h -1:关闭表头输出,直接返回计数数值- 注意:生产环境不要明文写密码,建议用环境变量或者加密存储的方式读取,比如
SQLSERVER_PWD=$(cat /path/to/encrypted/pwd | decryption_command)
三、完整的Shell脚本示例
把上面的逻辑整合起来,实现校验+自动重导:
#!/bin/bash # -------------------------- 配置参数 -------------------------- # Hive相关 HIVE_DB="your_hive_db" HIVE_TABLE="your_hive_table" HIVE_JDBC_URL="jdbc:hive2://hive-server:10000" HIVE_USER="hive_user" # SQL Server相关 SQLSERVER_HOST="sqlserver-host" SQLSERVER_PORT="1433" SQLSERVER_DB="sqlserver_db" SQLSERVER_TABLE="sqlserver_table" SQLSERVER_USER="sql_user" # 生产环境建议用环境变量传递密码 SQLSERVER_PWD="${SQLSERVER_PWD_ENV}" # Sqoop导出命令(替换为你的实际Sqoop脚本内容) SQOOP_CMD="sqoop export --connect jdbc:sqlserver://${SQLSERVER_HOST}:${SQLSERVER_PORT};databaseName=${SQLSERVER_DB} \ --username ${SQLSERVER_USER} \ --password ${SQLSERVER_PWD} \ --table ${SQLSERVER_TABLE} \ --export-dir /user/hive/warehouse/${HIVE_DB}.db/${HIVE_TABLE} \ --input-fields-terminated-by '\001' \ --m 1" # -------------------------------------------------------------- # 1. 统计Hive表行数 echo "开始统计Hive表行数..." hive_count=$(beeline -u "${HIVE_JDBC_URL}" -n "${HIVE_USER}" -e "select count(*) from ${HIVE_DB}.${HIVE_TABLE};" | grep -v "WARN" | grep -v "Connected" | tail -n 1) # 校验是否获取到有效数值 if ! [[ "${hive_count}" =~ ^[0-9]+$ ]]; then echo "ERROR: 无法获取Hive表行数" exit 1 fi echo "Hive表行数: ${hive_count}" # 2. 统计SQL Server表行数 echo "开始统计SQL Server表行数..." sqlserver_count=$(sqlcmd -S "${SQLSERVER_HOST},${SQLSERVER_PORT}" -U "${SQLSERVER_USER}" -P "${SQLSERVER_PWD}" -d "${SQLSERVER_DB}" -Q "select count(*) from ${SQLSERVER_TABLE};" -h -1) if ! [[ "${sqlserver_count}" =~ ^[0-9]+$ ]]; then echo "ERROR: 无法获取SQL Server表行数" exit 1 fi echo "SQL Server表行数: ${sqlserver_count}" # 3. 对比行数并执行重导逻辑 if [ "${hive_count}" -ne "${sqlserver_count}" ]; then echo "行数不一致,开始清空SQL Server表并重新导出..." # 清空SQL Server表(用truncate比delete更快) sqlcmd -S "${SQLSERVER_HOST},${SQLSERVER_PORT}" -U "${SQLSERVER_USER}" -P "${SQLSERVER_PWD}" -d "${SQLSERVER_DB}" -Q "truncate table ${SQLSERVER_TABLE};" # 执行Sqoop导出 ${SQOOP_CMD} if [ $? -eq 0 ]; then echo "重新导出完成,再次校验行数..." # 再次统计SQL Server行数 new_sqlserver_count=$(sqlcmd -S "${SQLSERVER_HOST},${SQLSERVER_PORT}" -U "${SQLSERVER_USER}" -P "${SQLSERVER_PWD}" -d "${SQLSERVER_DB}" -Q "select count(*) from ${SQLSERVER_TABLE};" -h -1) if [ "${hive_count}" -eq "${new_sqlserver_count}" ]; then echo "校验通过,数据导出成功!" else echo "ERROR: 重新导出后行数仍然不一致,请人工排查!" exit 1 fi else echo "ERROR: Sqoop重新导出失败!" exit 1 fi else echo "行数一致,无需执行导出操作" exit 0 fi
额外注意事项
- 如果Hive表是分区表,
count(*)会扫描全表数据,可能耗时较长,若追求速度可以考虑使用Hive的统计信息(ANALYZE TABLE生成),但准确性不如直接count。 sqlcmd的安装:CentOS/RHEL可以通过yum install mssql-tools安装,Ubuntu可以用apt-get install mssql-tools。- 脚本中加入了数值有效性校验,避免因日志格式变化导致获取到非数值的结果,提升稳定性。
内容的提问来源于stack exchange,提问作者Aakib
相关产品推荐
相关产品推荐

