有一批文本文件如下: numt_qe_0411.txt numt_qe_0412.txt numt_qe_0413.txt numt_qe_0414.txt ...
每个文件的内容格式如下: 9435446,问题1:,答案1 9575177,问题2? ,答案2 9575177,问题3? ,答案3 ...
可能存在以下几种情况: 1. 文件中有空行 2. 行中可能存在Tab符 3. 可能存在错误折行的情况,如: 9594287,您的性别:,男 9594287,您的年龄: ,70 ~80岁 9594287,您的学历:,大专
应为: 9594287,您的性别:,男 9594287,您的年龄: ,70~80岁 9594287,您的学历:,大专 要求将所有文件内容导入如下结构的 t1 表中:
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| sdate | date | YES | | NULL | |
| userid | bigint(20) | YES | | NULL | |
| qu_title | varchar(500) | YES | | NULL | |
| qu_item | varchar(255) | YES | | NULL | |
| dstate | int(255) | YES | | 0 | |
+----------+--------------+------+-----+---------+----------------+
第一个逗号之前为一列,对应到字段userid,最后一个逗号后面为第三个字段,对应到字段qu_item;中间内容对应到 字段qu_title;文件名中的日期,导入的时候写到字段 sdate。并且由于资源限制,一次性导入整个一个文件会使得服务器卡死。
先处理文本文件,去掉空行和Tab符号,然后将一个大文件分割成若干小文件。将每个小文件的数据导入一个中间过渡表,之后再将用SQL查询中的字符串和窗口函数处理后的结果插入目标表。
create table t_question (`txt` text) engine=innodb default charset=utf8mb4;
(1)改成unix格式
cd /data/software/xxqg/
dos2unix *.txt
(2)去掉空行
sed -i '/^$/d' *.txt
(3)Tab符替换为空格
sed -i 's/\t/ /g' *.txt
(4)分成100000行一个的小文件
mkdir small_file
cd small_file
split -l 100000 -d -a 5 ../numt_qe_0411.txt 04_11_
split -l 100000 -d -a 5 ../numt_qe_0412.txt 04_12_
split -l 100000 -d -a 5 ../numt_qe_0413.txt 04_13_
split -l 100000 -d -a 5 ../numt_qe_0414.txt 04_14_
...
(5)生成SQL命令文件
ls -l | awk '{print "truncate table t_question; load data infile '\''\/data\/software\/xxqg\/small_file\/"$9 "'\'' into table t_question ;"}' | grep 04 > sql_cmd.sql
#!/bin/bash
source ~/.bashrc
cat /data/software/xxqg/small_file/sql_cmd.sql|while read line
do
read mon day <<< `echo $line | awk -F/ '{print $6}' | awk -F_ '{print $1,$2}'`
sdate='2022-'$mon'-'$day
# userid >= 1000000 为正常数据
# userid < 1000000 为错误折行数据,用lag函数合并到上一行
# instr(reverse(txt),',') 取得最后一个逗号的位置
# sleep 1 为缓解负载压力
mysql -u root -p123456 -S /data/18251/mysqldata/mysql.sock -Dtest -e "${line}"
mysql -u root -p123456 -S /data/18251/mysqldata/mysql.sock -Dtest -e "
insert into t1 (sdate,userid,qu_title,qu_item)
select sdate,userid,qu_title,qu_item
from (select '$sdate' sdate,substring_index(txt,',',1) userid,substr(txt,instr(txt,',')+1,char_length(txt) - instr(reverse(txt),',')-instr(txt,',')) qu_title,substring_index(txt,',',-1) qu_item from t_question) t where userid >= 1000000;
insert into t1 (sdate,userid,qu_title,qu_item)
select '$sdate' sdate,substring_index(txt,',',1) userid,substr(txt,instr(txt,',')+1,char_length(txt) - instr(reverse(txt),',')-instr(txt,',')) qu_title,substring_index(txt,',',-1) qu_item
from (select concat(lag_txt,userid) txt from (select txt,substring_index(txt,',',1) userid,lag(txt,1) over () lag_txt from t_question) t where userid < 1000000) t;
commit;
"
sleep 1;
done