Выполнение одного дополнительного запроса для каждой записи - очень плохая идея и яркий пример проблемы N + 1 : где вам нужно получить «N» дочерних элементов сущности, и изначально была выбрана только родительская сущность .
Если у вашего исходного запроса 100 пользователей, вы закончите делать 101 запрос. Если позже вам понадобится какое-то другое несвязанное поле, оно начинает быстро выходить из-под контроля.
Это очень плохо для производительности , а поскольку ваше приложение усложняется, оно может очень легко иметь очень серьезное влияние на это.
Предполагая, что вы не можете изменить исходный запрос и выполнить простой запрос JOIN
для получения необходимых данных, лучше просто выполнить два запроса и сшить полученные данные. Даже если вы можете изменить исходный запрос, это может привести к лучшему выполнению.
Как go об этом:
Предполагая, что у вас есть исходный массив объектов с formId
и userId
publi c properties, сначала извлеките все интересующие вас идентификаторы пользователей:
$index = [];
$ids = array_reduce($array, function($ids, $object) use (&$index) {
$ids[] = $object->userId;
$index[$object->userId] = $object;
return $ids;
});
$ids_for_sql = '(' . implode(', ', $ids) . ')';
Вы также создаете "index" ($index
), чтобы иметь возможность доступа к объектам непосредственно в массив без необходимости повторять его снова.
Теперь вы можете сделать второй запрос, который вам нужен, чтобы получить свойство "group":
$groups_query = "SELECT userId, group from users WHERE userId IN $ids_for_sql";
Теперь это просто вопрос " сшивание "данных двух запросов:
foreach ($conn->query($groups_query) as $row) {
$index[$row['userId']]->group = $row['group'];
}
. Теперь ваш исходный $array
, содержащий" пользовательские "объекты, будет корректно обновлен, и выполнит только 2 запроса вместо 11 . Это работает и масштабируется лучше, без добавления существенной сложности.
Вы можете увидеть простую работающую демонстрацию (с массивами вместо SQL запросов) здесь .