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 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Python에서 최소 공배수를 찾는 알고리즘을 작성하는 방법은 무엇입니까? 최소공배수는 두 숫자를 나눌 수 있는 두 숫자 사이의 가장 작은 정수입니다. 수학에서 최소 공배수를 푸는 것은 기본적인 수학적 작업이며, 컴퓨터 프로그래밍에서는 Python을 사용하여 최소 공배수를 푸는 알고리즘을 작성할 수 있습니다. 다음은 기본적인 최소 공배수 알고리즘을 소개하고 구체적인 코드 예제를 제공합니다. 최소 공배수의 수학적 정의는 다음과 같습니다. a가 n으로 나누어지고 b가 n으로 나누어지면 n은 a와 b의 최소 공배수입니다. 최소값을 해결하려면

제목: C 언어 프로그래밍을 사용하여 최대 공약수 솔루션 구현 최대 공약수(Greatest Common Divisor, 줄여서 GCD)는 두 개 이상의 정수를 동시에 나눌 수 있는 가장 큰 양의 정수를 말합니다. 최대 공약수를 구하는 것은 일부 알고리즘 및 문제 해결에 매우 도움이 될 수 있습니다. 본 글에서는 최대공약수를 찾는 기능을 C언어 프로그래밍을 통해 구현하고, 구체적인 코드 예시를 제공하겠습니다. C 언어에서는 유클리드 알고리즘을 사용하여 최대값을 풀 수 있습니다.

Numpy는 Python의 잘 알려진 과학 컴퓨팅 라이브러리로, 대규모 다차원 배열 및 행렬을 처리하기 위한 풍부한 기능과 효율적인 컴퓨팅 방법을 제공합니다. 데이터 과학 및 기계 학습의 세계에서 행렬 반전은 일반적인 작업입니다. 이번 글에서는 Numpy 라이브러리를 이용하여 역행렬을 빠르게 푸는 방법을 소개하고 구체적인 코드 예시를 제공하겠습니다. 먼저 Numpy 라이브러리를 설치하여 Python 환경에 도입해 보겠습니다. Numpy는 다음 명령을 사용하여 터미널에 설치할 수 있습니다: pipinsta

Python을 사용하여 계승 해결 알고리즘을 구현하는 방법은 무엇입니까? 팩토리얼(Factorial)은 수학에서 중요한 개념입니다. 즉, 숫자에 자신의 마이너스 1을 곱한 다음 마이너스 1을 곱하고 계속해서 1이 되는 것을 의미합니다. 팩토리얼은 일반적으로 "!" 기호로 표시됩니다. 예를 들어 5의 팩토리얼은 5!로 표시되며 계산식은 5!=5×4×3×2×1=120입니다. Python에서는 루프를 사용하여 간단한 계승 알고리즘을 구현할 수 있습니다. 샘플 코드는 다음과 같습니다.

C 언어에서 최대 공약수를 찾는 방법을 배우려면 특정 코드 예제가 필요합니다. 최대 공약수(최대 공약수, 줄여서 GCD)는 이를 나눌 수 있는 두 개 이상의 정수 중에서 가장 큰 양의 정수를 나타냅니다. 최대 공통 분모는 특히 분수를 다루고, 분수를 단순화하고, 가장 간단한 정수 비율과 같은 문제를 해결할 때 컴퓨터 프로그래밍에서 자주 사용됩니다. 이 기사에서는 C 언어를 사용하여 최대 공약수를 찾는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 최대 공약수를 푸는 방법에는 유클리드와 같은 여러 가지 방법이 있습니다.

피보나치 수열은 다음 항이 이전 두 항의 합인 수열입니다. 피보나치 수열의 처음 두 항은 0 다음에 1이 옵니다. 이 문제에서는 피보나치 수열의 n번째 숫자를 구하겠습니다. 이를 위해 우리는 모든 숫자를 세고 n개의 항목을 인쇄합니다. 입력:8출력:011235813 설명 0+1=11+1=21+2=32+3=5 For 루프를 사용하여 처음 두 항목을 다음 항목으로 합산합니다. 예 #include<iostream>usingnamespacestd;intmain(){ intt1 = 0,t2=1,n,i,nextTerm;&am

여기서 우리는 모듈러 방정식과 관련된 흥미로운 문제를 보게 될 것입니다. A와 B라는 두 개의 값이 있다고 가정해 보겠습니다. (AmodX)=B가 유지되도록 변수 X가 취할 수 있는 가능한 값의 개수를 찾아야 합니다. A는 26이고 B는 2라고 가정합니다. 따라서 X의 선호 값은 {3,4,6,8,12,24}이므로 개수는 6입니다. 이것이 답입니다. 더 잘 이해하기 위해 알고리즘을 살펴보겠습니다. 알고리즘 가능WayCount(a,b)−begin ifa=b이면 무한한 해가 있습니다.

제목: PHP에서 2의 거듭제곱을 어떻게 풀 수 있나요? 특정 코드 예제는 PHP 프로그래밍에서 공유됩니다. 특히 일부 알고리즘과 수학적 계산에서는 숫자의 힘을 해결하는 것이 일반적인 요구 사항입니다. 이 기사에서는 PHP에서 2의 거듭제곱을 해결하는 방법을 자세히 설명하고 참조할 수 있는 특정 코드 예제를 제공합니다. PHP에서는 지수 연산자 **를 사용하여 거듭제곱을 계산할 수 있습니다. 2의 거듭제곱의 경우 $2^n$을 계산합니다. 여기서 $n$는 거듭제곱의 지수입니다. 아래에서는 이 계산을 몇 가지 다른 방법으로 구현해 보겠습니다. 방법 1: ** 행운을 이용하세요
