Вопрос или проблема
Здравствуйте, у меня есть этот код, который работает нормально, но я думаю, что он использует много ресурсов сервера, потому что выполняется запрос к базе данных для каждого идентификатора пользователя, хранящегося в группе. Есть ли способ решить эту проблему? Также как я могу использовать подготовленные выражения?
$event_start_date = date('d-m-Y', strtotime($new_start_date));
$notification = "Новое событие <span class="text-warning"><strong>$event_title</strong></span> начинается $event_start_date";
$notification_status = "0";
$notification_category= "events";
$sql = "SELECT user_join_id FROM user_group_join WHERE group_join_id='$event_group'";
$result= mysqli_query($conn,$sql);
$datas= array();
if(mysqli_num_rows($result) > 0){
while($row=mysqli_fetch_array($result, MYSQLI_ASSOC)){
$datas[]= $row;
}
}
foreach($datas as $data) {
$id_cliente = $data['user_join_id'];
$event_notification = mysqli_prepare($conn, "INSERT INTO user_notifications (notification_sent_by, notification_sent_to, notification_message, notification_time, notification_status, notification_category, notification_category_id) VALUES(?,?,?,now(),?,?,?)");
mysqli_stmt_bind_param($event_notification, 'iisisi', $userid, $id_cliente, $notification, $notification_status, $notification_category, $event_id);
mysqli_stmt_execute($event_notification);
mysqli_stmt_close($event_notification);
}
Большое спасибо за вашу помощь
Кроме того, вы подготавливаете выражение, используете его и затем закрываете на каждом шаге цикла. Это много потраченных усилий.
Подготовьте один раз, используйте в цикле, а затем закройте в конце.
$event_notification = mysqli_prepare($conn, "INSERT INTO user_notifications (notification_sent_by, notification_sent_to, notification_message, notification_time, notification_status, notification_category, notification_category_id) VALUES(?,?,?,now(),?,?,?)");
foreach($datas as $data) {
$id_cliente = $data['user_join_id'];
mysqli_stmt_bind_param($event_notification, 'iisisi', $userid, $id_cliente, $notification, $notification_status, $notification_category, $event_id);
mysqli_stmt_execute($event_notification);
}
mysqli_stmt_close($event_notification);
Я ожидаю, что это будет значительно быстрее.
Я не эксперт по mysqli и подготовленным выражениям, но я довольно уверен, что вы можете связать все данные в огромный массив и выполнить запрос сразу.
Этот ответ на SO предлагает мне это, в любом случае. Учитывая, что вы уже построили большой массив, вы должны иметь возможность использовать его без foreach
, чтобы не разбивать его обратно. Это может быть даже быстрее.
Ответ или решение
В вопросе, который вы подняли, заключается важная задача оптимизации запросов к базе данных в контексте использования языка программирования PHP с расширением mysqli. Сначала давайте рассмотрим текущую структуру кода, а затем предложим улучшения, которые помогут уменьшить нагрузку на сервер и ускорить выполнение операций с базой данных.
Анализ текущего кода
Исходя из предоставленного вами образца кода, мы видим, что вы выполняете выборку идентификаторов пользователей из таблицы user_group_join
, а затем, используя цикл foreach
, добавляете уведомления для каждого пользователя, выполняя при этом подготовленный SQL-запрос.
Проблемы текущего подхода:
- Множественные запросы к базе данных: Для каждого идентификатора пользователя создается новый запрос к базе данных, что существенно увеличивает время выполнения и создает ненужную нагрузку на сервер.
- Подготовка и закрытие запроса внутри цикла: Каждый раз, когда вы вызываете
mysqli_prepare
иmysqli_stmt_close
, вы тратите дополнительные ресурсы.
Оптимизация процесса вставки уведомлений
1. Подготовка одного запроса
Как вы правильно заметили, подготовленный запрос следует создавать вне цикла, а использовать его многократно внутри цикла. Таким образом, мы уменьшаем количество подготовительных операций.
Вот ваш оптимизированный код:
$event_start_date = date('d-m-Y', strtotime($new_start_date));
$notification = "Nuovo evento <span class='text-warning'><strong>$event_title</strong></span> inizia il $event_start_date";
$notification_status = "0";
$notification_category= "events";
$sql = "SELECT user_join_id FROM user_group_join WHERE group_join_id=?";
$stmt = mysqli_prepare($conn, $sql);
mysqli_stmt_bind_param($stmt, 'i', $event_group);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$datas = array();
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
$datas[] = $row;
}
mysqli_stmt_close($stmt);
if (!empty($datas)) {
// Подготовка единственного сообщения
$event_notification = mysqli_prepare($conn, "INSERT INTO user_notifications (notification_sent_by, notification_sent_to, notification_message, notification_time, notification_status, notification_category, notification_category_id) VALUES(?, ?, ?, NOW(), ?, ?, ?)");
foreach ($datas as $data) {
$id_cliente = $data['user_join_id'];
mysqli_stmt_bind_param($event_notification, 'iisisi', $userid, $id_cliente, $notification, $notification_status, $notification_category, $event_id);
mysqli_stmt_execute($event_notification);
}
mysqli_stmt_close($event_notification);
}
2. Пакетная вставка данных
Хотя использование одного подготовленного запроса в цикле – это уже шаг к оптимизации, существует еще более эффективный подход: выполнение пакетной вставки. Это позволит уменьшить количество обращений к базе данных и значительно снизит время выполнения всего скрипта.
Вы можете использовать следующий подход:
if (!empty($datas)) {
$sql_values = [];
foreach ($datas as $data) {
$id_cliente = $data['user_join_id'];
$sql_values[] = "($userid, $id_cliente, '$notification', NOW(), '$notification_status', '$notification_category', $event_id)";
}
// Формируем финальный SQL запрос
$sql_insert = "INSERT INTO user_notifications (notification_sent_by, notification_sent_to, notification_message, notification_time, notification_status, notification_category, notification_category_id) VALUES " . implode(',', $sql_values);
mysqli_query($conn, $sql_insert);
}
Заключение
В результате описанных выше шагов, вы сможете значительно сократить время, затрачиваемое на выполнение запросов к базе данных, что будет способствовать более эффективному использованию ресурсов вашего сервера. Подготовленные выражения и пакетная вставка являются важными инструментами для оптимизации взаимодействия с базой данных. Убедитесь, что при использовании пакетных вставок вы соблюдаете ограничения на количество строк, которые могут быть вставлены за один раз, в зависимости от вашей системы управления базами данных.