ホームページ > バックエンド開発 > PHPチュートリアル > PHPのpdo+mysqlループ挿入効率が極端に低いので解決してください

PHPのpdo+mysqlループ挿入効率が極端に低いので解決してください

WBOY
リリース: 2016-06-23 13:29:09
オリジナル
809 人が閲覧しました

オフィスオートメーションを実現するために、学生テーブルをデータベースにインポートする小さなものを作成しましたが、問題なく動作しますが、Baidu でインターネットを検索しても解決策が見つかりませんでした。 。
実現したい機能は次のとおりです。 1. インポート中の表示。処理結果を表示したい場合、スクロールバーが常に下に表示され、最新の処理結果が表示されます。以下では、コード内でアンカーポイントの配置を使用しましたが、これは非常に愚かに感じられました~~~ この要件を満たすより良い方法はありますか?

2. インポートするとき、最初の 1500 項目は非常に速くインポートされ、スクロール バーは下までスクロールしました (非常にプロフェッショナルな外観) が、約 1500 項目を過ぎると動かなくなりました。データベースを選択し、stutable からカウント (*) を選択すると、レコードが増加していることがわかりましたが、ページがスタックしているようで、どの接続をクリックしても応答がありません。同時に、データベース内の行数が表示されません。まだまだ成長中~~~。ここ 2 日間、Baidu はこの問題に直面し、InnoDB には行ロックとトランザクションがあるため、MyIsam よりも効率が低いと述べています (ただし、トランザクションが必要であり、複数のプロジェクトが 1 つのサーバー上にあり、mysql エンジンを変更できません)。ストアドプロシージャやイベントを使えばいいという人もいますが、ストレージやイベントを使った場合、リアルタイム処理の効果は現れません。それを解決したい場合は、my.cnf などの設定ファイルを変更できないため、現在のページで解決できることを願っています~~~~

主に 2 番目の問題で、2 日間私を苦しめました、解決してくださいそれ~ ~~~この質問をこのバージョンで投稿するのが良いのか、データベース バージョンで投稿する方が良いのかまだわかりません~~~
コードから始めましょう:

<?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 タグ内に出力されますか、それともタグ外に出力されますか?
外だったら明らかに間違ってるよ

テーブルの閉店マークはどこにあるの? ! !自分でも調べてみましたが、 が と書かれていませんでした~~~~ かなり不注意だったようです!


ループによる の出力はテーブルに出力されますが、ループのため、テーブルはループが完了した後にのみ閉じることができます

モデレータのおかげで、より良いものがあります瞬時に表示する方法は?ループ内で「<script>$.get()</script>」をエコーする必要がありますか?これは、PHP ループ内で jq を使用して別のページからデータを送信し、テーブルにレシートを書き込むことを意味しますか?

最も重要な問題はインポート効率です。インポートされたアイテムの数が約 1,500 に達すると、ページは完全にスタックしますが、データベース内の行数は依然として増加しています。ページがフリーズするのは PHP が原因なのか、それともデータベースへのデータの挿入がページをフリーズさせるのかわかりません。

疑問を解決します

一般的に、マークが閉じられていない場合、マークの内容は表示されません

そのため、内容を表示するには table の代わりに div を使用する必要があり、IE の table は読み取り専用です
別の方法 (ajax など) は、現在使用している方法よりも明らかに優れています。少なくとも、項目が挿入されるたびにプログラムを人為的に 1 ミリ秒間ハングさせる必要はありません

テストの結果、ブラウザーがハングアップしないことがわかりました。 Insert ステートメントをコメントアウトしたのですが、PHP の foreach で表示されるだけでもフリーズしてしまうようです。

解決策はありますか?

このようなニーズの場合、私は通常、フロントエンドの ajax ループリクエストを使用し、毎回 n 回処理し、成功が返された後にページに表示し、再度リクエストします
個人的には、Web は小規模な用途に適していると思いますGPU が CPU を処理できないのと同じように、同時実行性の高いタスク 動作は同じです


このようなニーズには、通常、フロントエンドの ajax ループリクエストを使用し、毎回 n を処理し、正常に返された後にページに表示します、そして再度リクエストします

個人的には、Web は小規模なタスクと高い同時実行性に適していると思います。GPU が CPU の計算を処理できないのと同じです


大量のデータがある場合にこれをテストしました。 、処理されたデータを取得するために jquery を使用し、データが多すぎるとブラウザがフリーズします



フロントエンドの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()方法回显,效果不错。

感谢大家热心回复,结贴

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート