Скорость / лучшая практика промывки mysqli multi query()

я съежилась, когда Себастьян заявил, что он отключает и снова подключается между каждым использованием mysqli_multi_query() @ может ли mysqli_multi_query делать операторы обновления? потому что это просто не казалось передовой практики.

, Крейг @ multi_query mysqli, то последует запрос заявил в своем случае, что было быстрее отключить и снова подключиться между каждым использованием mysqli_multi_query() чем использовать mysqli_next_result().

Я хотел бы спросить, есть ли у кого-нибудь еще знание из первых рук или эталонные данные, чтобы предложить приблизительное " отсечение "(на основе объема запроса или что-то еще), когда программист должен выбрать" новое соединение "по сравнению с методом" следующего результата".

Я тоже рад услышать любые соображения, не относящиеся к скорости. Имеет ли использование Крейгом соединительной функции какое-либо отношение к скорости?

есть ли разница в скорости между утверждением Крейга while:

while ($mysqli->next_result()) {;}

и

какое-то время заявление, которое я предлагаю:

while(mysqli_more_results($mysqli) && mysqli_next_result($mysqli));

и

создание нового подключения для каждого ожидаемого multi_query, перед запуском первого multi_query. Я только что проверил это, и два mysqli_multi_query()s были без ошибок = нет close() требуется:

$mysqli1=mysqli_connect("$host","$user","$pass","$db");
$mysqli2=mysqli_connect("$host","$user","$pass","$db");

и

Открытие и закрытие между mysqli_multi_query() как Себастьян и Крейг:

$mysqli = newSQL();
$mysqli->multi_query($multiUpdates);
$mysqli->close();

и

у кого-нибудь есть другой вариант для тестирования?

2 ответов


это не next_result() виноват, но запрашивает себя. Время выполнения кода зависит от времени выполнения фактических запросов.

хотя mysqli_multi_query() возвращает управление довольно быстро,это не означает, что все запросы были выполнены к тому времени. совсем наоборот, к тому времени mysqli_multi_query() закончил, выполнен только первый запрос. в то время как все другие запросы поставлены в очередь на стороне mysql для асинхронные исполнение.

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

зная, что вы уже можете сказать, какой путь выбрать: если вы не заботитесь о результатах, вы мая просто закрыть соединение. Но на самом деле, это будет просто подметать грязь под ковром, оставляя все медленные запросы на месте. Итак, это лучше держать next_result() цикл на месте (особенно потому, что вам нужно проверить наличие ошибок / затронутых строк / и т. д. в любом случае), но ускорить сами запросы.

Итак, получается, что решить проблему с next_result() вы должны фактически решить регулярную проблему скорости запроса. Итак, вот некоторые рекомендации:

  1. для выбранных запросов это обычное индексирование / объяснение анализа, уже объясненное в других ответах.
  2. для запросов DML, особенно запускаются партиями, есть и другие способы:

говоря о случае Крейга, это очень напоминает известную проблему скорости innodb пишет. По умолчанию InnoDB engine настроен в очень осторожный режим, где не выполняется следующая запись, пока двигатель не гарантирует, что предыдущий был успешно завершен. Она пишет ужасно медленно (что-то вроде только 10 запросов/сек). Общим обходным путем для этого является создание всех записей сразу. Для запросов insert существует множество методов:

  • вы можете использовать синтаксис вставки нескольких значений
  • вы можете использовать LOAD DATA INFILE query
  • вы можете обернуть все запросы в транзакции.

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

 $multiSQL = "BEGIN;{$multiSQL}COMMIT;";
 $mysqli->multi_query($multiSQL);
 while ($mysqli->next_result()) {/* check results here */}

если это не сработает/неприменимо в вашем случае, то я бы предложил изменить mysqli_multi_query() для одиночные запросы выполняются в цикле, исследуют и оптимизируют скорость, а затем возвращаются к multi_query.


чтобы ответить на ваш вопрос:

посмотреть, прежде чем прыгать

жду mysqli_more_results() call (взгляд перед прыжком), не ускоряет вещи: если у вас есть n результатов, вы будете делать (2*n) -1 вызовы в базу данных, в то время как Крейг делает n+1.

несколько соединений

multi_query выполняет async, поэтому вы просто добавите накладные расходы на подключение.

Открытие и закрытие db

слушать Ваш Общий Смысл ; -) но не теряйте след того, что вы делаете. Обертывание запросов в транзакцию, сделает их атомные. Это означает, что они все плохо, или все получится. Иногда это требуются база данных никогда не конфликтует с вашей вселенной дискурса. Но использование транзакций для ускорения может иметь нежелательные побочные эффекты. Рассмотрим случай, когда один ваших запросов нарушает ограничение. Что сделает всю транзакцию неудачной. Это означает, что если они не были логической транзакцией в первую очередь, и большинство запросов должны были преуспеть, что вам придется выяснить, что пошло не так, а что придется переиздать. стоимостью вы вместо того, чтобы обеспечить ускорение.

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

вместо этого попробуйте вспомнить

ложки нет

в ваших примерах не было необходимости в нескольких запросах. The вставить ... Значения форма принимает несколько кортежей для значений. Так что вместо того, чтобы готовить один подготовленное заявление и оберните его повторные исполнения в транзакцию как подсказывает ваш здравый смысл. Вы можете подготовить один оператор, выполнить его и автоматически зафиксировать. Согласно руководство в mysqli это экономит вам кучу roundtrips.

поэтому сделайте заявление SQL формы:

INSERT INTO r (a, b, c) VALUES (?, ?, ?), (?, ?, ?), ...

и связать и выполнить его. mysqldump -- opt делает это, так почему бы и нет? Справочное руководство mysql как раздел по оптимизации операторов. Посмотрите в его разделе DML для запросов вставки и обновления. Но понимание почему --opt делает то, что он делает, это хорошее начало.

недооцененное значение подготовки заявление

для меня реальная ценность подготовленных заявлений -не что вы можете выполнить их несколько раз, но автоматический вход экранирования. Для жалкого одного дополнительного клиента-сервера туда и обратно вы спасаете себя от SQL-инъекции. SQL-инъекция является серьезной точкой внимания, особенно когда вы используете multi_query. multi_query говорит mysql ожидал несколько запросов и выполнить них. Так что не сумей сбежать как следует, и тебе конец. немного веселья:

Exploits of a mom

моя лучшая практика будет:

  1. Я действительно нужно несколько запросов?
  2. если я это сделаю, побег ну или готовить них!