php的pdo+mysql循环insert效率极低,求解
为了实现办公自动化,我做了一个导入学生表到数据库的小东西,运行虽然没问题,但是效率极低,百度遍网络没有发现解决方案,特来求教。
想要实现的功能是:
1,边导入边显示,这个已经实现,但是效果不理想,我想要显示处理结果的时候滚动条始终在最下方这样就能显示最新处理的数据了,下面的代码中我使用了锚点定位,觉得很笨~~~对于这个需求有更好的方法吗?
2,导入时大约前1500条导入非常快,显示的效果也很赞,滚动条狂滚动至最下方(很专业的样子哈),但是到了大约1500条以后就卡壳了,打开数据库select count(*) from stutable,却发现记录是一直在增长,但是页面看上去卡死了,点任何连接都没有响应,同时数据库的行数仍然在增长~~~。这两天百度这个问题,说是InnoDB是行锁并且有事务所以效率比MyIsam低(但是我需要事务,并且好几个项目都在一台服务器上我不能把mysql的引擎改掉)。也有人说用存储过程或事件,但是如果用存储或事件的话就看不到实时处理的效果了。如果要解决的话,我还是希望在当前这个页面就能搞好,因为不能修改my.cnf等之类的配置文件~~~~
主要是第二个问题,折磨了我两天,求解~~~~还有不知道这个问题发在本版好还是数据库版好~~~
先上代码:
<?phpinclude("conn.php");?><!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>批量导入</title></head><body><table> <thead> <tr><th colspan=2>批量导入学生信息</th></tr> <tr><td>姓名</td><td>导入结果</td></tr> </thead> <tbody><?php//因为导入数据可能占用较长时间,因此设置超时时间为0set_time_limit(0);//将信息写入数据库function addstu($stuname){ global $db; if($db->exec("insert into stutable(stuname) values('".$stuname."')")=="1") { return "导入成功!"; } else { return "导入失败!"; }}//上传部分不写了,只写插入过程if($_POST){ //文件导入 if($_FILES["stuinfo"]["error"]>0) { echo "<tr><td colspan='3'>上传文件出错,错误信息:".$_FILES["stuinfo"]["error"]."</td></tr>"; } else { $extension=pathinfo($_FILES["stuinfo"]["name"],PATHINFO_EXTENSION);//获取上传文件的扩展名 $filename="upload/".time().".".$extension;//上传后的文件名 move_uploaded_file($_FILES["stuinfo"]["tmp_name"],$filename);//将上传的临时文件移动到指定目录 $file=fopen($filename,"r");//打开文件,然后读取信息 $stuinfo=array(); while($data=fgetcsv($file)) { array_push($stuinfo,implode($data)); } fclose($file); } //遍历数组,向数据库insert数据 print str_repeat(" ",4096);//想实现导入的同时显示进度,先输出一堆空字符 foreach($stuinfo as $rs) { $addresult=""; $addresult="<tr><td><a name='".$rs."'></a>".$rs."</td><td>".addstu($rs)."</td><tr>";//直接调用addstu方法向数据库写数据 $addresult.="<script type='text/javascript'>location.href='#".$rs."';</script>";//想实现导入的同时滚动条始终在最下方,想不到别的方法,只得用锚点定位。请问有更好的方法吗? echo $addresult;//输出当前的操作 ob_flush(); flush(); usleep(1000);//当时无论如何都实现不了边导入边显示,后来加了个sleep就行了,百思不解,请指点 }}?> </tbody></table></body></html>
回复讨论(解决方案)
无论是 InnoDB 还是 MyIsam,表类型都是针对表的
你这种即时显示方式是构建在一个 web 系统缺陷上的,换一个环境可能就完全无效了
你输出的数据中 tr 标记未封闭,即使能显示,也是有问题的
你的 表行是输出到 table 标记中呢,还是标记外?
在外显然是不对的,在内的话你的 table 闭标记又在哪呢
哇版主好认真~!!!我自己还检查了一遍,也没发现把写成了
循环输出的
版主大大,还有更好的即时显示方式吗?难道要在循环中echo "<script>$.get()</script>"这种方式也就是在PHP的循环中使用jq来从另一个页面提交数据然后将回执写在table中?
最主要的是导入效率问题,导入到1500条左右的时候,页面完全就卡死了,但是数据库的行数还是在增加的。我不清楚是php导致页面卡死还是向数据库插入数据导致页面卡死?
求解惑
一般的说,标记未封闭时,标记的内容是不会显示的
所以你应该用 div 而不是 table 显示内容,况且 IE 中的 table 是只读的
换一种方式(比如 ajax)显然要比你现在的要好,至少不需要人为的使程序每插入一条就挂起1毫秒
经过测试发现,浏览器不是在Insert过程中卡死的,我把insert语句注释,单纯显示“导入成功”字符,也会卡死
看来是在php的foreach中卡死的
难道浏览器不能显示这么多信息?
有没有解决方法?
像这种需求我一般是用前端的ajax循环请求,每次处理n个,返回成功后显示在页面中,然后再请求
个人觉得web就是适合小任务高并发,就像GPU不能处理CPU的运算一样
像这种需求我一般是用前端的ajax循环请求,每次处理n个,返回成功后显示在页面中,然后再请求
个人觉得web就是适合小任务高并发,就像GPU不能处理CPU的运算一样
这个我测试过,如果数据很多,浏览器也会卡死,我是用jquery获取处理的数据,然后$.append将返回信息显示,数据多了也会卡死
像这种需求我一般是用前端的ajax循环请求,每次处理n个,返回成功后显示在页面中,然后再请求
个人觉得web就是适合小任务高并发,就像GPU不能处理CPU的运算一样
这个我测试过,如果数据很多,浏览器也会卡死,我是用jquery获取处理的数据,然后$.append将返回信息显示,数据多了也会卡死
有2个需要注意的地方:
不要连续发请求,采用回调的方式,当第一组数据处理+显示完成后,再发起第二组数据的请求
如果数据量太大,就给显示数据条数定个上限,当达到上限时,再有新数据,就先删掉等量的最老的数据
这样做之后肯定不会卡的
如果你的需求就是把上万的数据一并显示在窗口中的话,就要考虑js缓存然后动态变化显示内容了
首先把全部数据保存在js变量中,把前100条打印出来,然后绑定个页面滚动事件,到底了自动刷出来新的100条,把老的删除
归根到底就是不要创建过多DOM元素
估计浏览器把内存都占了。所以后面解释就慢,你创建了太多dom了。
定位到最底可以不用描点实现,可以用js,修改scrolltop=scrollheight来实现。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title></title></head><body><script type="text/javascript">function add(){var now = new Date();var div = document.getElementById('scrolldIV');div.innerHTML = div.innerHTML + 'time_' + now.getTime() + '<br />';div.scrollTop = div.scrollHeight;}</script><span class="notice">请点击“插入一行”按钮,插入最新信息,当出现滚动条时,滚动条将自动保持在底部。</span><br /><div id="scrolldIV" style="overflow:auto; height: 100px; width: 400px; border: 1px solid #999;"></div><input type="button" value="插入一行" onclick="add();"></div></div></body></html>
回复楼上版主,为什么变慢我还是不清楚原因,不知道是因为创建的DOM太多缘故还是PHP代码缘故。
不过我现在的方案是:使用jquery的$().append()方法回显,效果不错。
感谢大家热心回复,结贴

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何用Python寫出求解最小公倍數的演算法?最小公倍數是指兩個數中能夠整除這兩個數的最小整數。在數學中,求解最小公倍數是一項基本的數學任務,而在電腦程式設計中,我們可以使用Python來寫一個求解最小公倍數的演算法。以下將介紹基本的最小公倍數演算法,並給出具體的程式碼範例。最小公倍數的數學定義是:若a能被n整除且b能被n整除,則n是a和b的最小公倍數。要求解最小

標題:以C語言程式實現最大公約數求解最大公約數(GreatestCommonDivisor,簡稱GCD)是指能夠同時整除兩個或多個整數的最大正整數。求解最大公約數對於一些演算法和問題解決非常有幫助。在本文中,將透過C語言程式設計來實現求解最大公約數的功能,並提供具體的程式碼範例。在C語言中,可以使用歐幾裡得演算法(EuclideanAlgorithm)來求解最大

Numpy是Python中著名的科學計算庫,為處理大型多維數組和矩陣提供了豐富的功能和高效的計算方法。在資料科學和機器學習領域,矩陣的逆運算是一項常見的任務。在本文中,我將介紹使用Numpy函式庫快速求解矩陣逆的方法,並提供具體的程式碼範例。首先,讓我們透過安裝Numpy庫引入它到我們的Python環境中。可以使用以下命令在終端機中安裝Numpy:pipinsta

如何使用Python實作求解階乘的演算法?階乘是數學中的重要概念,指的是一個數乘上其自身減一,再乘上自身減一減一,以此類推,直到乘到1為止。階乘通常以符號"!"來表示,例如5的階乘表示為5!,計算公式為:5!=5×4×3×2×1=120。在Python中,我們可以使用迴圈來實作一個簡單的階乘演算法。下面給一個範例程式碼:deffacto

學習C語言如何解最大公約數,需要具體程式碼範例最大公約數(GreatestCommonDivisor,簡稱GCD)是指兩個或多個整數中能夠整除它們的最大正整數。在電腦程式設計中常會用到最大公約數,特別是在處理分數、化簡分數以及求解最簡整數比例等問題時。本篇文章將介紹如何使用C語言來求解最大公約數,並給出具體的程式碼範例。求解最大公約數的方法有很多種,例如歐

在這裡,我們將看到一個與模方程式相關的有趣問題。假設我們有兩個值A和B。我們必須找到變數X可以取的可能值的數量,使得(AmodX)=B成立。假設A為26,B為2。所以X的首選值會是{3,4,6,8,12,24},因此計數為6。這就是答案。讓我們看一下演算法以更好地理解。演算法possibleWayCount(a,b)−begin ifa=b,thenthereareinfinitesolutions ifa

斐波那契數列是一個數列,其中下一項是前兩項之和。斐波那契數列的前兩項是0後跟1。在這個問題中,我們會發現斐波那契數列中的第n個數字。為此,我們將計算所有數字並列印n項。 Input:8Output:011235813說明0+1=11+1=21+2=32+3=5使用For迴圈將前兩項求和作為下一項範例#include<iostream>usingnamespacestd;intmain(){ intt1= 0,t2=1,n,i,nextTerm;&am

標題:PHP中如何求解2的乘方?具體程式碼範例分享在PHP程式設計中,求解數的乘方是一個常見的需求,特別是在一些演算法和數學計算中。本文將詳細探討如何在PHP中求解2的乘方,並提供具體的程式碼範例供大家參考。在PHP中,可以使用冪運算子**來計算乘方。對於2的乘方,即計算$2^n$,其中$n$是乘方的指數。下面我們將透過幾種不同的方法來實現這個計算。方法一:使用**運
