ホームページ バックエンド開発 PHPチュートリアル MySQL のクエリに関する PHP 同時実行の例 (図)

MySQL のクエリに関する PHP 同時実行の例 (図)

May 24, 2018 am 09:21 AM
mysql php

この記事では主にMySQLのPHP同時クエリのサンプルコードを紹介していますが、編集者が非常に良いと思ったので、参考として共有させていただきます。エディターをフォローして見てみましょう

私は最近 PHP を勉強していて、とても気に入っています。PHP での MySQL の同時クエリの問題に遭遇しました。ちなみに、勉強してメモを残しました。 query

これは最も一般的なものです。呼び出しモードでは、クライアントは Query[関数] を呼び出し、クエリ コマンドを開始し、結果が返されるのを待って、結果を読み取り、次に 2 番目のクエリ コマンドを送信し、返される結果を取得し、その結果を読み取ります。所要時間の合計は、2 つのクエリの時間の合計になります。たとえば、以下に示すようにプロセスを簡略化します。

サンプル画像、1.1 から 1.3 は Query [関数] の呼び出しです。2 つのクエリは 1.1、1.2、1.3、2.1、2.2、2.3 を通過します。特に 1.2 と 2.2 では、ブロックされて待機し、プロセスは他のことを行うことができません。

同期呼び出しの利点は、直感的な考え方に準拠しており、呼び出しと処理が簡単であることです。欠点は、結果が返されるのを待ってプロセスがブロックされ、実行時間が余分にかかることです。
複数のクエリリクエストがある場合、またはプロセスが他の処理を行っている場合、待ち時間を合理的に利用してプロセスの処理能力を向上させることは可能ですか?


分割

次に、Query [関数] を分割します。クライアントは 1.1 の直後に戻り、1.2 をスキップして 1.3 にデータが到着した後にデータを読み取ります。このようにして、プロセスは元の 1.2 の段階から解放され、別の SQL クエリ [2.1] を開始するなど、より多くのことを実行できるようになります。並行クエリのプロトタイプを見たことがありますか?

同時クエリ

同期クエリと比較して、同時クエリでは、前のクエリリクエストが開始された直後に次のクエリリクエストを開始できます。以下に示すように、プロセスを簡略化します。

例の図では、1.1.1 でリクエストが正常に送信された後、すぐに [1.1.2] が返され、最終的なクエリ結果がリモート 1.2 で返されます。ただし、1.1.1 と 1.2 の間では、この期間中に 2 つのクエリ リクエストが同時に開始され、2.2 は 1.2 よりも前に到着したため、2 つのクエリの合計時間は の時間と同じでした。最初のクエリ。

同時クエリの利点は、プロセスの使用率を向上させ、サーバーによるクエリの処理のブロックと待機を回避し、複数のクエリの時間を短縮できることです。ただし、欠点も明らかです。N 個の同時クエリを開始するには、データベース接続プールを備えたアプリケーションの場合、この状況を回避できます。

縮退

理想的には、N 個のクエリを同時に実行し、合計の消費時間はクエリ時間が最も長いクエリと同じになるようにする必要があります。ただし、同時クエリが [同期クエリ] に [縮退] する可能性もあります。何?例の図では、2.1.1 より前に 1.2 が返された場合、同時クエリは [同期クエリ] に [縮退] しますが、コストは同期クエリよりも高くなります。

多重化

クエリ1を開始
  • クエリ2を開始
  • クエリ3を開始
  • クエリ1を待機中、クエリ2. Query3
  • はquery2の結果を読み取ります
  • クエリ 1 の結果を読む
  • クエリ 3 の結果を読む
  • では、クエリ結果がいつ返されるか、どのクエリ結果が返されるかを知るには、どうやって待つのでしょうか?

クエリ IO ごとに read を呼び出しますか?ブロッキング IO が発生した場合、1 つの IO でブロックされ、他の IO では結果が返され、処理できなくなります。したがって、ノンブロッキング IO の場合、いずれかの IO がブロックされることを心配する必要はありません。ただし、ポーリングと判定が継続的に発生し、CPU リソースが浪費されます。

この状況では、多重化を使用して複数の IO をポーリングできます。

PHP は MySQL を実装します

PHP の mysqli (mysqlnd ドライバー) は、多重ポーリング IO (mysqli_poll) と非同期クエリ (MYSQLI_ASYNC、mysqli_reap_async_query) を提供します。サンプル コード:

<?php
 $sqls = array(
  &#39;SELECT * FROM `mz_table_1` LIMIT 1000,10&#39;,
  &#39;SELECT * FROM `mz_table_1` LIMIT 1010,10&#39;,
  &#39;SELECT * FROM `mz_table_1` LIMIT 1020,10&#39;,
  &#39;SELECT * FROM `mz_table_1` LIMIT 10000,10&#39;,
  &#39;SELECT * FROM `mz_table_2` LIMIT 1&#39;,
  &#39;SELECT * FROM `mz_table_2` LIMIT 5,1&#39;
 );
 $links = [];
 $tvs = microtime();
 $tv = explode(&#39; &#39;, $tvs);
 $start = $tv[1] * 1000 + (int)($tv[0] * 1000);
 // 链接数据库,并发起异步查询
 foreach ($sqls as $sql) { 
  $link = mysqli_connect(&#39;127.0.0.1&#39;, &#39;root&#39;, &#39;root&#39;, &#39;dbname&#39;, &#39;3306&#39;);
  $link->query($sql, MYSQLI_ASYNC); // 发起异步查询,立即返回
  $links[$link->thread_id] = $link;
 }
 $llen = count($links);
 $process = 0;
 do {
  $r_array = $e_array = $reject = $links;
  // 多路复用轮询IO
  if(!($ret = mysqli_poll($r_array, $e_array, $reject, 2))) {
   continue;
  }
  // 读取有结果返回的查询,处理结果
  foreach ($r_array as $link) {
   if ($result = $link->reap_async_query()) {
    print_r($result->fetch_row());
    if (is_object($result))
     mysqli_free_result($result);
   } else {
   }
   // 操作完后,把当前数据链接从待轮询集合中删除
   unset($links[$link->thread_id]);
   $link->close();
   $process++;
  }
  foreach ($e_array as $link) {
   die;
  }
  foreach ($reject as $link) {
   die;
  }
 }while($process < $llen);
 $tvs = microtime();
 $tv = explode(&#39; &#39;, $tvs);
 $end = $tv[1] * 1000 + (int)($tv[0] * 1000);
 echo $end - $start,PHP_EOL;
ログイン後にコピー

mysqli_poll ソースコード:

#ifndef PHP_WIN32
#define php_select(m, r, w, e, t) select(m, r, w, e, t)
#else
#include "win32/select.h"
#endif
/* {{{ mysqlnd_poll */
PHPAPI enum_func_status
mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long sec, long usec, int * desc_num)
{
 struct timeval tv;
 struct timeval *tv_p = NULL;
 fd_set   rfds, wfds, efds;
 php_socket_t max_fd = 0;
 int    retval, sets = 0;
 int    set_count, max_set_count = 0;
 DBG_ENTER("_mysqlnd_poll");
 if (sec < 0 || usec < 0) {
  php_error_docref(NULL, E_WARNING, "Negative values passed for sec and/or usec");
  DBG_RETURN(FAIL);
 }
 FD_ZERO(&rfds);
 FD_ZERO(&wfds);
 FD_ZERO(&efds);
 // 从所有mysqli链接中获取socket链接描述符
 if (r_array != NULL) {
  *dont_poll = mysqlnd_stream_array_check_for_readiness(r_array);
  set_count = mysqlnd_stream_array_to_fd_set(r_array, &rfds, &max_fd);
  if (set_count > max_set_count) {
   max_set_count = set_count;
  }
  sets += set_count;
 }
 // 从所有mysqli链接中获取socket链接描述符
 if (e_array != NULL) {
  set_count = mysqlnd_stream_array_to_fd_set(e_array, &efds, &max_fd);
  if (set_count > max_set_count) {
   max_set_count = set_count;
  }
  sets += set_count;
 }
 if (!sets) {
  php_error_docref(NULL, E_WARNING, *dont_poll ? "All arrays passed are clear":"No stream arrays were passed");
  DBG_ERR_FMT(*dont_poll ? "All arrays passed are clear":"No stream arrays were passed");
  DBG_RETURN(FAIL);
 }
 PHP_SAFE_MAX_FD(max_fd, max_set_count);
 // select轮询阻塞时间
 if (usec > 999999) {
  tv.tv_sec = sec + (usec / 1000000);
  tv.tv_usec = usec % 1000000;
 } else {
  tv.tv_sec = sec;
  tv.tv_usec = usec;
 }
 tv_p = &tv;
 // 轮询,等待多个IO可读,php_select是select的宏定义
 retval = php_select(max_fd + 1, &rfds, &wfds, &efds, tv_p);
 if (retval == -1) {
  php_error_docref(NULL, E_WARNING, "unable to select [%d]: %s (max_fd=%d)",
      errno, strerror(errno), max_fd);
  DBG_RETURN(FAIL);
 }
 if (r_array != NULL) {
  mysqlnd_stream_array_from_fd_set(r_array, &rfds);
 }
 if (e_array != NULL) {
  mysqlnd_stream_array_from_fd_set(e_array, &efds);
 }
 // 返回可操作的IO数量
 *desc_num = retval;
 DBG_RETURN(PASS);
}
ログイン後にコピー

同時クエリ操作の結果

効果をより直感的に確認するために、操作用に最適化されていない 1 億 3,000 万のデータ量を持つテーブルを見つけました。

同時クエリの結果:

同期クエリの結果:

この結果から、同期クエリの合計消費時間は、すべてのクエリの時間の合計です。同時クエリの消費量は実際に最も長いクエリです (同期クエリの 4 番目のクエリには数秒かかりますが、これは同時クエリの合計時間と一致します)。また、同時クエリのクエリ順序は次のクエリとは異なります。結果が到着する順序。

クエリ時間が短い複数のクエリの比較

クエリ時間が短い複数の SQL クエリを使用して比較します

同時クエリのテスト 1 結果 (データベースリンク時間もカウントされます):

同期の結果クエリ (データベース リンク時間もカウントされます):

同時クエリのテスト 2 の結果 (データベース リンク時間はカウントされません):

結果から判断すると、同時クエリ テスト1は恩恵を受けませんでした。同期クエリの観点から見ると、各クエリには約 3 ~ 4 ミリ秒かかります。ただし、データベース接続時間が統計に含まれていない場合 (同期クエリにはデータベース接続が 1 つしかありません)、同時クエリの利点が再び反映される可能性があります。

結論

ここでは、PHP での同時クエリ MySQL の実装について説明し、実験結果から同時クエリの長​​所と短所を直観的に理解しました。データベース接続を確立する時間が、最適化された SQL クエリの大部分を占めます。 #接続プールがないのですが、何に使いますか

以上がMySQL のクエリに関する PHP 同時実行の例 (図)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHPの未来:適応と革新 PHPの未来:適応と革新 Apr 11, 2025 am 12:01 AM

PHPの将来は、新しいテクノロジーの傾向に適応し、革新的な機能を導入することで達成されます。1)クラウドコンピューティング、コンテナ化、マイクロサービスアーキテクチャに適応し、DockerとKubernetesをサポートします。 2)パフォーマンスとデータ処理の効率を改善するために、JITコンパイラと列挙タイプを導入します。 3)パフォーマンスを継続的に最適化し、ベストプラクティスを促進します。

PHP対Python:違いを理解します PHP対Python:違いを理解します Apr 11, 2025 am 12:15 AM

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHPは、シンプルな構文と高い実行効率を備えたWeb開発に適しています。 2。Pythonは、簡潔な構文とリッチライブラリを備えたデータサイエンスと機械学習に適しています。

MySQL:簡単な学習のためのシンプルな概念 MySQL:簡単な学習のためのシンプルな概念 Apr 10, 2025 am 09:29 AM

MySQLは、オープンソースのリレーショナルデータベース管理システムです。 1)データベースとテーブルの作成:createdatabaseおよびcreateTableコマンドを使用します。 2)基本操作:挿入、更新、削除、選択。 3)高度な操作:参加、サブクエリ、トランザクション処理。 4)デバッグスキル:構文、データ型、およびアクセス許可を確認します。 5)最適化の提案:インデックスを使用し、選択*を避け、トランザクションを使用します。

phpmyadminを開く方法 phpmyadminを開く方法 Apr 10, 2025 pm 10:51 PM

次の手順でphpmyadminを開くことができます。1。ウェブサイトコントロールパネルにログインします。 2。phpmyadminアイコンを見つけてクリックします。 3。MySQL資格情報を入力します。 4.「ログイン」をクリックします。

MySQLおよびSQL:開発者にとって不可欠なスキル MySQLおよびSQL:開発者にとって不可欠なスキル Apr 10, 2025 am 09:30 AM

MySQLとSQLは、開発者にとって不可欠なスキルです。 1.MYSQLはオープンソースのリレーショナルデータベース管理システムであり、SQLはデータベースの管理と操作に使用される標準言語です。 2.MYSQLは、効率的なデータストレージと検索機能を介して複数のストレージエンジンをサポートし、SQLは簡単なステートメントを通じて複雑なデータ操作を完了します。 3.使用の例には、条件によるフィルタリングやソートなどの基本的なクエリと高度なクエリが含まれます。 4.一般的なエラーには、SQLステートメントをチェックして説明コマンドを使用することで最適化できる構文エラーとパフォーマンスの問題が含まれます。 5.パフォーマンス最適化手法には、インデックスの使用、フルテーブルスキャンの回避、参加操作の最適化、コードの読み取り可能性の向上が含まれます。

PHP:それは死にかけていますか、それとも単に適応していますか? PHP:それは死にかけていますか、それとも単に適応していますか? Apr 11, 2025 am 12:13 AM

PHPは死にかけていませんが、常に適応して進化しています。 1)PHPは、1994年以来、新しいテクノロジーの傾向に適応するために複数のバージョンの反復を受けています。 2)現在、電子商取引、コンテンツ管理システム、その他の分野で広く使用されています。 3)PHP8は、パフォーマンスと近代化を改善するために、JITコンパイラおよびその他の機能を導入します。 4)Opcacheを使用してPSR-12標準に従って、パフォーマンスとコードの品質を最適化します。

phpmyAdmin接続mysql phpmyAdmin接続mysql Apr 10, 2025 pm 10:57 PM

phpmyadminを使用してmysqlに接続する方法は? phpmyadminにアクセスするためのURLは、通常、http:// localhost/phpmyadminまたはhttp:// [サーバーIPアドレス]/phpMyAdminです。 MySQLユーザー名とパスワードを入力します。接続するデータベースを選択します。 [接続]ボタンをクリックして、接続を確立します。

SQLが行を削除した後にデータを回復する方法 SQLが行を削除した後にデータを回復する方法 Apr 09, 2025 pm 12:21 PM

データベースから直接削除された行を直接回復することは、バックアップまたはトランザクションロールバックメカニズムがない限り、通常不可能です。キーポイント:トランザクションロールバック:トランザクションがデータの回復にコミットする前にロールバックを実行します。バックアップ:データベースの定期的なバックアップを使用して、データをすばやく復元できます。データベーススナップショット:データベースの読み取り専用コピーを作成し、データが誤って削除された後にデータを復元できます。削除ステートメントを使用して注意してください:誤って削除されないように条件を慎重に確認してください。 WHERE句を使用します:削除するデータを明示的に指定します。テスト環境を使用:削除操作を実行する前にテストします。

See all articles