为了实现办公自动化,我做了一个导入学生表到数据库的小东西,运行虽然没问题,但是效率极低,百度遍网络没有发现解决方案,特来求教。
想要实现的功能是:
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 闭标记又在哪呢
哇版主好认真~!!!我自己还检查了一遍,也没发现把写成了
一般的说,标记未封闭时,标记的内容是不会显示的
所以你应该用 div 而不是 table 显示内容,况且 IE 中的 table 是只读的
换一种方式(比如 ajax)显然要比你现在的要好,至少不需要人为的使程序每插入一条就挂起1毫秒
经过测试发现,浏览器不是在Insert过程中卡死的,我把insert语句注释,单纯显示“导入成功”字符,也会卡死
看来是在php的foreach中卡死的
难道浏览器不能显示这么多信息?
有没有解决方法?
像这种需求我一般是用前端的ajax循环请求,每次处理n个,返回成功后显示在页面中,然后再请求
个人觉得web就是适合小任务高并发,就像GPU不能处理CPU的运算一样
像这种需求我一般是用前端的ajax循环请求,每次处理n个,返回成功后显示在页面中,然后再请求
个人觉得web就是适合小任务高并发,就像GPU不能处理CPU的运算一样
像这种需求我一般是用前端的ajax循环请求,每次处理n个,返回成功后显示在页面中,然后再请求
个人觉得web就是适合小任务高并发,就像GPU不能处理CPU的运算一样
如果你的需求就是把上万的数据一并显示在窗口中的话,就要考虑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()方法回显,效果不错。
感谢大家热心回复,结贴