PHP-асинхронный mysql-запрос

Мое приложение сначала запрашивает 2 больших набора данных, затем выполняет некоторую работу над первым набором данных и «использует» его на втором.

Если возможно, мне бы хотелось, чтобы он вместо этого выполнял только первый набор синхронно, а второй асинхронно, выполнял работу над первым набором, а затем дождался завершения запроса второго набора, если он еще не был и, наконец, использует первый набор данных по нему.

Возможно ли это как-то?

Возможно.

$mysqli->query($long_running_sql, MYSQLI_ASYNC); echo 'run other stuff'; $result = $mysqli->reap_async_query(); //gives result (and blocks script if query is not done) $resultArray = $result->fetch_assoc(); 

Или вы можете использовать mysqli_poll, если вы не хотите иметь блокирующий вызов

http://php.net/manual/en/mysqli.poll.php

MySQL требует, чтобы внутри одного соединения запрос полностью обрабатывался до запуска следующего запроса . Это включает в себя выбор всех результатов .

Однако можно:

  • извлекать результаты один за другим, а не сразу
  • запуск нескольких запросов путем создания нескольких соединений

По умолчанию PHP будет ждать, пока все результаты будут доступны, а затем внутренне (в драйвере mysql) сразу выберут все результаты. Это справедливо даже при использовании, например, PDOStatement::fetch() чтобы импортировать их в ваш код по одной строке за раз. При использовании PDO это может быть предотвращено с установкой атрибута \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY на false . Это полезно для:

  • ускоряя обработку результатов запроса: ваш код может начать обработку, как только будет найдена одна строка, а не только после того, как будет найдена каждая строка.
  • работа с наборами результатов, которые потенциально больше, чем память, доступная для PHP ( встроенная память памяти RAM RAM или RAM).

Имейте в виду, что часто скорость ограничена системой хранения с характеристиками, которые означают, что общее время обработки для двух запросов больше при одновременном их запуске, чем при их запуске один за другим.

Пример (который можно сделать полностью в MySQL, но для показа концепции …):

 $dbConnectionOne = new \PDO('mysql:hostname=localhost;dbname=test', 'user', 'pass'); $dbConnectionOne->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $dbConnectionTwo = new \PDO('mysql:hostname=localhost;dbname=test', 'user', 'pass'); $dbConnectionTwo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $dbConnectionTwo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); $synchStmt = $dbConnectionOne->prepare('SELECT id, name, factor FROM measurementConfiguration'); $synchStmt->execute(); $asynchStmt = $dbConnectionTwo->prepare('SELECT measurementConfiguration_id, timestamp, value FROM hugeMeasurementsTable'); $asynchStmt->execute(); $measurementConfiguration = array(); foreach ($synchStmt->fetchAll() as $synchStmtRow) { $measurementConfiguration[$synchStmtRow['id']] = array( 'name' => $synchStmtRow['name'], 'factor' => $synchStmtRow['factor'] ); } while (($asynchStmtRow = $asynchStmt->fetch()) !== false) { $currentMeasurementConfiguration = $measurementConfiguration[$asynchStmtRow['measurementConfiguration_id']]; echo 'Measurement of sensor ' . $currentMeasurementConfiguration['name'] . ' at ' . $asynchStmtRow['timestamp'] . ' was ' . ($asynchStmtRow['value'] * $currentMeasurementConfiguration['factor']) . PHP_EOL; }