php实现mysql百万级数据插入,耗时10s左右
如题,最近做的一个项目,需求就是这样,写个功能模块,实现批量导入,为客服省点时间(好吧,需求就是需求)。好在插入的数据,都是些连续的数字,所以可以利用
foreach循环出这些数据,然后拼接成mysql的insert语句,进行大字段的批量插入。原理就是这么个原理,当然过程中有坑,什么打开扩展限制,暂且只看逻辑方面的吧。
框架的话,不是laravel,用的ci,实例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | /** * @desc 批量导入百万条数据入库(方法已经写通用,数据最少5000条,最大100W条) * @date 2017-10-26 20:45:45 * @param [int $start_no 起始号;int $end_no 截止号;string $express_type 类型] * @author 1245049149@qq.com * @return [type] */ public function import_million_express_no () { //基本数据设置 header( 'Content-Type:text/html;charset=utf-8' ); ini_set ( 'memory_limit' , '128M' ); //设置类型对应数据库中的表名 $express_to_form = [ 'test1' => 'from1' , //平台1对应的表名 'test2' => 'from2' , //平台2对应的表名 ]; //获取参数 $start_no = trim( $this ->input->post( 'start_no' )); $end_no = trim( $this ->input->post( 'end_no' )); $express_type = trim( $this ->input->post( 'express_type' )); //判断参数是否存在 if (! $start_no || ! $end_no ){ echo '<script>alert("录入失败,起始号和截止号不能为空为0");history.back();</script>' ; return ; } //起始单号不能大于等于截止单号,录入数量至少为5000个 if ( $start_no >= $end_no ) { echo '<script>alert("起始号不能,大于等于截止号!");history.back();</script>' ; return ; } else { if ( $end_no - $start_no < 5000) { echo '<script>alert("每次录入号不能小于5000个!");history.back();</script>' ; return ; } if ( $end_no - $start_no > 1000000) { echo '<script>alert("每次录入号不能大于1000000个!");history.back();</script>' ; return ; } } //判断数据类型是否存在 $table_name = $express_to_form [ $express_type ]; if (! $table_name ){ echo '<script>alert("快递类型有误,无法进行打印!");history.back();</script>' ; return ; } else { //判断初始单号,截止单号是否已经录入 $sql1 = "select id from {$table_name} where express_no = {$start_no}" ; $res1 = $this ->db->query( $sql1 )->row(); if ( $res1 ){ echo '<script>alert("起始号已存在!");history.back();</script>' ; return ; } $sql2 = "select id from {$table_name} where express_no = {$end_no}" ; $res2 = $this ->db->query( $sql2 )->row(); if ( $res2 ){ echo '<script>alert("截止号已存在!");history.back();</script>' ; return ; } } /***上面的一系列判断的废话可以不用看,直接看下面怎么对数据进行逻辑处理***/ //将起始号和截止号进行区间划分 $length = $end_no - $start_no + 1; $times = floor ( $length / 5000); $temp_data = []; for ( $i =0; $i < $times ; $i ++){ $temp_data [ $i ][ 'start_no' ] = $start_no ; //起始编号 $temp_data [ $i ][ 'end_no' ] = $start_no + 4999; //结束编号 $start_no += 5000; //下一轮循环的起始编号 } //检验数组最后一组数据,判断是否需要再添加 if ( $end_no > $temp_data [ $times -1][ 'end_no' ]){ $temp_data [ $times ][ 'start_no' ] = $temp_data [ $times -1][ 'end_no' ] + 1; $temp_data [ $times ][ 'end_no' ] = $end_no ; } //进行导入数据库sql语句的拼接 $add_time = time(); $add_user = $this ->session->userdata[ 'user_name' ]; $tmp_val = "('{$add_time}','$add_user',0,'%s',0)," ; for ( $j =0; $j < count ( $temp_data ); $j ++){ //循环拼接sql插入语句 $sql = "insert into {$table_name} (field1,field2,field3,field4,field5) values " ; for ( $i = $temp_data [ $j ][ 'start_no' ]; $i <= $temp_data [ $j ][ 'end_no' ]; $i ++) { $sql .= sprintf( $tmp_val , $i ); } $sql = trim( $sql , ',' ) . ';' ; $bool = $this ->db->query( $sql ); //执行插入有误,写进日志异常表from3中 if (! $bool ){ // 记录日志 $log_info = array (); $log_info [ 'field1' ] = time(); $log_info [ 'field2' ] = '类型:' . $express_type . '执行有误,单号' . $temp_data [ $j ][ 'start_no' ]. '-' . $temp_data [ $j ][ 'end_no' ]. '执行失败' ; $log_info [ 'field3' ] = $this ->session->userdata[ 'user_name' ]; $this ->db->insert( 'from3' , $log_info ); //错误日志标志 $err_log_info = TRUE; } } //数据返回 if ( $err_log_info ){ echo '<script>alert("部分号执行失败,请联系管理员解决!");history.back();</script>' ; } else { echo '<script>alert("数据执行成功!!!");history.back();</script>' ; } return ; } |
上面就是封装的一个完整的类,参数验证什么的,可以不用看了,直接看sql语句拼接,其实最后发现吧,做出来也没啥。经过测试,基本耗时在10s左右徘徊,恩恩,暂时先这样,有好的思路,欢迎交流。不说了,得继续加班去了,233
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 开发的设计和重构,为开发效率服务
· 从零开始开发一个 MCP Server!
· Ai满嘴顺口溜,想考研?浪费我几个小时
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想