如何基于日期列将大型MySQL表拆分导出至不同文本/CSV文件?
兄弟,我太懂你这种用Python逐行处理百万级数据慢到崩溃的感受了!把所有数据拉到应用层再逐行判断写入,光是数据传输和反复IO的开销就够磨人的。给你几个从数据库层面直接操作的高效方案,比你现在的方法快N倍:
方案1:用MySQL原生
SELECT INTO OUTFILE结合存储过程循环导出 这是最直接的数据库原生方案,让MySQL直接把每个日期的数据写入对应文件,完全绕开应用层的开销。
首先创建一个存储过程来处理循环导出:
DELIMITER // CREATE PROCEDURE export_data_by_date() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE current_date DATE; -- 游标获取所有唯一的日期值(如果date_col是字符串类型,要转成DATE类型,比如STR_TO_DATE(date_col, '%d-%m-%Y')) DECLARE date_cursor CURSOR FOR SELECT DISTINCT DATE(date_col) FROM your_table_name; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN date_cursor; export_loop: LOOP FETCH date_cursor INTO current_date; IF done THEN LEAVE export_loop; END IF; -- 拼接导出SQL,格式化日期为文件名要求的格式 SET @export_sql = CONCAT( 'SELECT col_1, col_2, date_col INTO OUTFILE ''/your/export/directory/', DATE_FORMAT(current_date, '%d_%m_%Y'), '.csv'' FIELDS TERMINATED BY '' '' OPTIONALLY ENCLOSED BY ''"'' LINES TERMINATED BY ''\n'' FROM your_table_name WHERE DATE(date_col) = ''', current_date, ''';' ); PREPARE stmt FROM @export_sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END LOOP; CLOSE date_cursor; END // DELIMITER ;
然后执行存储过程即可:
CALL export_data_by_date();
⚠️ 注意事项:
- MySQL用户需要拥有
FILE权限 - 指定的导出目录必须是MySQL进程有权限写入的路径(可以用
SHOW VARIABLES LIKE 'secure_file_priv';查看允许的导出目录) - 如果你的
date_col是字符串格式(比如'20-12-2021'),要把DATE(date_col)改成STR_TO_DATE(date_col, '%d-%m-%Y')来正确转换日期
方案2:用Shell脚本配合
mysql命令批量导出 如果不想写存储过程,用Shell脚本更灵活,适合运维同学或者喜欢命令行的场景:
#!/bin/bash # 配置数据库参数 DB_NAME="your_database_name" TABLE_NAME="your_table_name" EXPORT_DIR="/path/to/your/export/folder" DB_USER="your_mysql_user" DB_PASS="your_mysql_password" # 创建导出目录(如果不存在) mkdir -p $EXPORT_DIR # 获取所有唯一的日期值(同样注意字符串日期的转换) dates=$(mysql -u$DB_USER -p$DB_PASS $DB_NAME -se "SELECT DISTINCT DATE(date_col) FROM $TABLE_NAME;") # 循环每个日期导出数据 for date in $dates; do # 格式化日期为文件名需要的格式 formatted_date=$(date -d "$date" +%d_%m_%Y) # 执行查询并导出到对应CSV文件 mysql -u$DB_USER -p$DB_PASS $DB_NAME -se "SELECT col_1, col_2, date_col FROM $TABLE_NAME WHERE DATE(date_col) = '$date';" > "$EXPORT_DIR/$formatted_date.csv" done
给脚本加执行权限后运行即可:
chmod +x export_script.sh ./export_script.sh
方案3:用
mysqldump按日期分片导出 如果数据量超大,mysqldump是更稳定的选择,它专门用于大表备份导出,性能拉满:
#!/bin/bash DB_NAME="your_database_name" TABLE_NAME="your_table_name" EXPORT_DIR="/path/to/your/export/folder" DB_USER="your_mysql_user" DB_PASS="your_mysql_password" mkdir -p $EXPORT_DIR dates=$(mysql -u$DB_USER -p$DB_PASS $DB_NAME -se "SELECT DISTINCT DATE(date_col) FROM $TABLE_NAME;") for date in $dates; do formatted_date=$(date -d "$date" +%d_%m_%Y) # 用mysqldump导出指定日期的数据,--no-create-info表示不导出表结构 mysqldump -u$DB_USER -p$DB_PASS $DB_NAME $TABLE_NAME --where="DATE(date_col) = '$date'" --no-create-info --tab="$EXPORT_DIR" # 重命名导出的文件(默认是TABLE_NAME.txt) mv "$EXPORT_DIR/$TABLE_NAME.txt" "$EXPORT_DIR/$formatted_date.csv" done
如果需要逗号分隔的CSV,可以加上参数:--fields-terminated-by=',' --fields-enclosed-by='"'
为什么这些方案比Python逐行快?
你之前的Python方案需要把所有百万条数据从数据库拉到应用内存,再逐行判断写入文件,中间经历了「数据库→应用层→文件」的多环节传输和处理;而上面的方案都是让数据库直接把结果输出到文件,或者通过命令行直接定向到文件,省去了应用层的内存占用和反复IO开销,百万级数据下速度能提升几个数量级。
内容的提问来源于stack exchange,提问作者Atif
相关产品推荐
相关产品推荐

