整理sql数据

整理sql数据

脚本

#!/usr/bin/bash
cd /path/to/data/dir

#data file 可以换成其他方式,这里写死了
# for file in `ls |grep 'prefix' | grep 'suffix'` 可以换成这种方式,如果文件太多的话
file=(data1.sql data2.sql data.sql) # 写死了
for i in ${file[@]}; do # 遍历文件
    #获取表名,将表名放入临时文件(这里是tables)中
    cat  $i | grep 'CREATE TABLE' | awk -F\`  '{print $2}' > tables
    cat tables | while read line #遍历文件中的表名
    do
        echo $line
        # 根据表名取inset语句的前5000条数据存入文件中
        cat $i | grep 'INSERT INTO `'${line}'`' | head -n 5000  >> data.sql
    done
done

rm tables # 删除临时文件

不足

临时文件 tables

原计划不是把表名存入临时文件,而是使用下面的语句把表名保存到变量中,数组。但是没有成功

cat  ucr_iom_data.sql | grep 'CREATE TABLE' | awk -F\`  '{print $2}'

内存 反复读取文件

当前的脚本会反复读取文件,会导致很大的cpu和io消耗
原本涉及的算法是使用grep命令,使读取后的文件直接分组(按照表名),而后直接取分组后的前5000条数据。但是,使用grep分组本人还不会
分组的操作类似spark或者flink中的流式api,读取一次文件转换为流后即可一次操作,完成所有功能。

更改-根据表名拆分文件

使用shell命令拆分

#!/usr/bin/bash
path1=/path/to/data/file
cd $path1
file=(data1.sql data2.sql data3.sql)

for i in ${file[@]}; do
	cat $i | while read line
	do
		# echo $line
		insert=$(echo $line | awk '{print  $1 }' )
		
		if [[ $insert == "INSERT" ]] ; then
		    #echo $insert ;
		    name=$(echo $line | awk -F\` '{print  $2 }' )
		    # 这里tables目录应该使用脚本创建,而非手动
		    echo $line >> ${path1}/tables/${name}.sql
		fi
	done
done

但是这样处理太慢了,有一个4G的文件(处理这个文件的时候很慢);原因应该是按行处理。

使用sed命令拆分

#!/usr/bin/bash
path1=/path/to/data
cd $path1
file=(data1 data2 data3)
for i in ${file[@]}; do

    cat  $i | grep 'CREATE TABLE' | awk -F\`  '{print $2}' > temp_table_${i}
    cat temp_table_${i} | while read line
    do
        # echo $line
        echo "/INSERT INTO \`${line}\`/p"
        sed -n -e "/INSERT INTO \`${line}\`/p" $i > ${path1}/data_table/${line}.sql
    done
done

使用sed后快多了

附录

原文件的内容说明

原文件是3个,每个文件中包含建表和插入语句。每个文件不止包含一张表,最少的一个文件包含50张表。文件也比较大,最小的文件是300M,而最大的那个由4G。所以手工操作并不会简单多少。

另一种解决方法

使用python或java(本职工作是java开发)处理这个功能
本人近期对shell脚本十分着迷,特别是sed和awk的编辑功能
并且,使用shell可以写更少的代码,而达到相似的功能。
由于本人的shell脚本方面知识的不足,所以感觉十分难写,并且效果/效率不是很好

posted @ 2021-01-25 15:57  漫步ing  阅读(135)  评论(0编辑  收藏  举报