shell脚本的方式批量导出hive建表语句

因公司集群不支持hive命令,只能用beeline,但导出结果有多余信息且-e只能跟一条sql,故用spark - sql编写脚本。第一版执行慢,优化后又出现分号添加问题,最终利用sed和awk结合解决,强调解决问题的思维方式很重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近遇到的一个工作任务。由于公司集群不支持使用hive命令,只能使用beeline命令。
通过beeline -e  或 beeline -f 导出的结果,会包含一些其他多余的信息,不好过滤。
同时beeline -e 只能跟一条sql语句。
于是使用spark-sql来完成脚本编写。

第一版

spark-sql -e "use test ; show tables;" > tables.txt
    cat tables.txt | awk '{print$2}' |while read eachline
    #由于用spark-sql查询出的表信息包含三列,分别是库名 表名 false  用awk筛选出第二列的表名。
    do
    spark-sql -e "use test ; show create table $eachline;" >>tablesDDL.sql
    echo ";" >> tablesDDL.sql
    #在每条建表语句后追加分号,以便用于批量建表。
done

问题:执行速度非常慢,每循环一次,就会启停一次spark-sql客户端,浪费时间和集群资源。
优化执行脚本:
将循环产生的查询建表语句的sql先重定向到txt文件中,再使用spark-sql -f sql文件 的方式。
就只需要启动一次spark-sql客户端。

spark-sql -e "use $1 ; show tables;" > tables.txt
cat tables.txt | awk '{print$2}' |while read eachline
do
  echo "show create table $1.$eachline;" >>CreateTable.hql
done
#kinit -kt **** ****  
spark-sql -f CreateTable.hql > tablesDDL.hql

产生一个新的问题:每条建表语句间的分号就只能手动添加了???
于是,想到了用sed -i "s/^)$/);/g" 去匹配每条sql语句结束的)并替换为);。
但是发现我想多了,仔细查看sql语句,并不是只有每条sql语句结束了的最后单行为),在中间还有一处也是
单行一个).
怎么办呢? 想了半天,又想到一种方法可行。观察了各建表语句,发现了一条规律就是,
每条语句结束的上一行都是'numRows' = '-1'。于是可以利用sed命令打印出匹配该内容的行数,
然后再利用awk的算法运算去+1行,就得到了每条建表语句结束的那一行的行数,最后再用sed -i去匹配替换指定的行的内容。

搞定收工。

sed -n -e "/'numRows' = '-1'/="  tablesDDL.hql | awk '{print$1+1}' | while read line
    do 
      sed -i "${line}s/)/);/g" tablesDDL.hql
    done

虽然这只是一个简单的脚本,但发现了一些问题,就应该去一步步地思考如何解决。
这最重要的还是这种思考问题解决问题的思维方式。
加油!!!

<think>我们参考了多个引用,特别是引用[2]中提到了使用Shell脚本处理StarRocks表结构导出,可以借鉴其思路。在StarRocks中创通常是通过SQL语句完成的,我们可以编写一个包含创SQL的Shell脚本,并通过StarRocks客户端执行该SQL。基本思路:1.编写创的SQL语句,保存到一个字符串或SQL文件中。2.使用StarRocks的客户端(如mysql命令)连接到StarRocks并执行SQL。示例脚本如下:注意:在脚本中,我们使用mysql客户端作为StarRocks的客户端,因为StarRocks兼容MySQL协议。假设我们有如下的创SQL:```sqlCREATETABLEIFNOTEXISTStest_db.test_table(idINTCOMMENT"ID",nameVARCHAR(50)COMMENT"姓名",ageTINYINTCOMMENT"年龄",create_timeDATECOMMENT"创日期")ENGINE=olapDUPLICATEKEY(id)COMMENT"OLAP"DISTRIBUTEDBYHASH(id)BUCKETS10PROPERTIES("replication_num"="3");```我们可以将其嵌入到Shell脚本中:```bash#!/bin/bash#StarRocks连接信息HOST="your_starrocks_host"PORT="9030"#默认查询端口USER="root"PASSWORD=""#数据名DB_NAME="test_db"TABLE_NAME="test_table"#创的SQL语句CREATE_TABLE_SQL="CREATETABLEIFNOTEXISTS${DB_NAME}.${TABLE_NAME}(idINTCOMMENT'ID',nameVARCHAR(50)COMMENT'姓名',ageTINYINTCOMMENT'年龄',create_timeDATECOMMENT'创日期')ENGINE=olapDUPLICATEKEY(id)COMMENT'OLAP'DISTRIBUTEDBYHASH(id)BUCKETS10PROPERTIES('replication_num'='3');"#使用mysql客户端连接StarRocks执行SQLmysql-h${HOST}-P${PORT}-u${USER}-p${PASSWORD}-e"${CREATE_TABLE_SQL}"```注意事项:1.请根据实际修改连接信息、数据名、名和表结构。2.如果密码为空,可以省略-p参数,但如果有密码,-p后直接接密码(注意:-p与密码之间没有空格,否则会认为是密码以空格开始)。3.如果表结构复杂,也可以将SQL语句存放在一个单独的文件中,然后使用`source`命令或者重定向输入执行。另外,引用[2]中展示了如何从Shell脚本中提取模型(DUPLICATEKEY、PRIMARYKEY等),这提示我们可以将表结构信息存储在变量中,然后动态生成SQL语句。例如,我们可以这样动态生成:```bash#!/bin/bashHOST="your_starrocks_host"PORT="9030"USER="root"PASSWORD=""DB_NAME="test_db"TABLE_NAME="test_table"#定义表结构字段FIELDS="idINTCOMMENT'ID',nameVARCHAR(50)COMMENT'姓名',ageTINYINTCOMMENT'年龄',create_timeDATECOMMENT'创日期'"#模型(例如DUPLICATEKEY)TABLE_MODEL="DUPLICATEKEY(id)"#分桶方式DISTRIBUTE_KEY="HASH(id)BUCKETS10"#动态生成SQLCREATE_TABLE_SQL="CREATETABLEIFNOTEXISTS${DB_NAME}.${TABLE_NAME}(${FIELDS})ENGINE=olap${TABLE_MODEL}COMMENT'OLAP'DISTRIBUTEDBY${DISTRIBUTE_KEY}PROPERTIES('replication_num'='3');"mysql-h${HOST}-P${PORT}-u${USER}-p${PASSWORD}-e"${CREATE_TABLE_SQL}"```这种方式更灵活,可以方便地通过变量控制表结构。引用[2]中通过SQL查询获取模型信息,但我们的需求是创,所以不需要查询已有表结构,直接定义即可。因此,使用Shell脚本在StarRocks中创的核心就是构造创的SQL语句,然后通过StarRocks的客户端执行该SQL。另外,也可以考虑从外部文件读取表结构定义,或者使用函数封装重复操作等,以满足批量的需求。参考引用[4]中批量查看大小的思路,我们也可以批量。例如,遍历一个包含名和表结构的配置文件,循环执行创的SQL。例如,有一个定义文件tables_def.txt,每行包含名和表结构(可以用特定分隔符),然后在Shell脚本中读取每一行,解析并执行。但注意:表结构定义可能比较复杂,包含换行等,所以这种方式可能不太适合复杂的多行文本。因此,可以考虑每个一个SQL文件,然后循环执行SQL文件。下面是一个批量的示例,假设我们在一个目录下存放了多个创的SQL文件,文件命名规范为:名.sql```bash#!/bin/bashHOST="your_starrocks_host"PORT="9030"USER="root"PASSWORD=""DB_NAME="test_db"#SQL文件存放的目录SQL_DIR="/path/to/sql_dir"#遍历目录中的所有.sql文件forsql_filein$(ls${SQL_DIR}/*.sql)do#执行SQLmysql-h${HOST}-P${PORT}-u${USER}-p${PASSWORD}${DB_NAME}< ${sql_file}done```或者,如果定义在一个配置文件中,我们也可以动态生成SQL(需要定义文件设计得足够简单,比如每行字段用逗号分隔等)。但考虑到字段类型和约束等可能比较复杂,这种简单格式可能难以达,因此推荐使用独立的SQL文件方式。综上所述,根据创的数量以及表结构的复杂程度,可以选择直接嵌入SQL语句、动态生成SQL语句、执行外部SQL文件等方式。以上便是使用Shell脚本在StarRocks中创的方法。§§相关问题§§1.如何用Shell脚本在StarRocks中批量多个?2.如何动态生成StarRocks的字段定义?3.如何调整StarRocks的副本数量(replication_num)?4.在Shell脚本中如何安全地传递StarRocks的密码?</think> 了解您的需求!以下是通过 Shell 脚本在 StarRocks 中创的完整解决方案,结合参考引用内容整理的最佳实践: ### Shell 脚本在 StarRocks 中创示例 ```bash #!/bin/bash # StarRocks 连接配置 HOST="your_host" PORT="9030" # 默认查询端口 USER="root" PASSWORD="your_password" DB_NAME="your_database" # 创SQL(含日期分区) CREATE_TABLE_SQL=$(cat <<EOF CREATE TABLE IF NOT EXISTS $DB_NAME.sales ( order_id BIGINT COMMENT "订单ID", product VARCHAR(50) COMMENT "产品名称", sale_date DATE COMMENT "销售日期" ) ENGINE=olap DUPLICATE KEY(order_id) PARTITION BY RANGE(sale_date)( START ("2023-01-01") END ("2024-01-01") EVERY (INTERVAL 1 DAY) ) DISTRIBUTED BY HASH(order_id) BUCKETS 10 PROPERTIES ( "replication_num" = "3", "storage_format" = "v2" ); EOF ) # 执行命令(通过mysql协议) mysql -h$HOST -P$PORT -u$USER -p$PASSWORD -e "$CREATE_TABLE_SQL" # 验证是否创成功 VERIFY_SQL="SHOW TABLES FROM $DB_NAME LIKE 'sales';" mysql -h$HOST -P$PORT -u$USER -p$PASSWORD -e "$VERIFY_SQL" ``` ### 关键要素说明 1. **SQL 动态生成** - 使用 `$(cat <<EOF ... EOF)` 处理多行SQL - 变量嵌入名和数据名(参考引用[2][^2]) 2. **表结构设计** ```sql PARTITION BY RANGE(sale_date) -- 日期分区(yyyy-mm-dd格式) DISTRIBUTED BY HASH(order_id) -- 分布式键(参考引用[2][^2]) PROPERTIES ("replication_num" = "3") -- 副本配置 ``` 3. **分区转换技巧**(解决日期格式问题) ```sql -- 将Hive的yyyymmdd转换为yyyy-mm-dd PARTITION BY RANGE(FROM_UNIXTIME(UNIX_TIMESTAMP(sale_date, 'yyyyMMdd'))) ``` 适用于需要兼容Hive分区格式的场景(参考引用[1][^1]) 4. **批量扩展** ```bash # 批量(参考引用[3][^3]) TABLES=("table1" "table2" "table3") for table in "${TABLES[@]}"; do # 动态生成不同的DDL mysql -h$HOST -P$PORT -u$USER -p$PASSWORD -e "${CREATE_SQL//sales/$table}" done ``` ### 最佳实践议 1. **权限管理** ```bash # 使用最小权限账号执行(参考引用[5][^5]) USER="etl_user" # 专用ETL账户 ``` 2. **表结构检查** ```bash # 检查是否存在(参考引用[4][^4]) CHECK_SQL="SELECT COUNT(1) FROM information_schema.tables WHERE table_schema='$DB_NAME' AND table_name='sales'" ``` 3. **错误处理机制** ```bash if ! mysql -h$HOST -P$PORT -u$USER -p$PASSWORD -e "$CREATE_TABLE_SQL"; then echo "失败! 错误码:$?" >> $LOG_FILE exit 1 fi ``` ### 常见问题解决方案 1. **日期格式冲突** 如参考引用[1][^1]所述,使用`FROM_UNIXTIME`转换Hive格式分区: ```sql PARTITION BY RANGE(FROM_UNIXTIME(UNIX_TIMESTAMP(sale_date, 'yyyyMMdd'))) ``` 2. **大表结构管理** - 使用`DISTRIBUTED BY HASH`分桶 - 设置`BUCKETS`数为节点数的10倍(参考引用[3][^3]) 3. **生产环境优化** ```sql PROPERTIES ( "enable_persistent_index" = "true", -- 开启持久化索引 "compression" = "LZ4" -- 压缩算法 ) ``` (基于引用[5][^5]的运维议)
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值