@arsenaljek

Как правильно вывести данные, минимизируя количество запросов?

Расскажите самый верный способ, вывода данных из mysql. Например я хочу вывести аккордеон. В названии аккордеона я хочу выводить город и справа выводить количество элементов внутри. Т.е это один запрос. Внутри аккордеона я хочу вывести дилеров которые относятся к этому городу. Т.е второй запрос у нас получается в цикле первого. А еще к примеру я захочу вывести рядом еще один аккордеон, который будет выводить, скажем дилеров за рубежом. Это еще + 2 запроса и один из них в цикле. Т.е получается очень много запросов. Как грамотно подходить к этой проблеме?
Для наглядности вот код вывода 1 аккордеона.

$sql = 'SELECT (SELECT COUNT(*) FROM `dilery` WHERE dilery.city_dil = city.id_city AND dilery.`status` != 1) as `count`, city.name_city, city.id_city
FROM dilery
INNER JOIN city ON dilery.city_dil = city.id_city
WHERE city.region != "1" AND dilery.`status` != 1
GROUP BY name_city
ORDER BY name_city';
$row_dealers = mysqli_query($link,$sql); 
while ($row = mysqli_fetch_array($row_dealers)) { ?>

<div class="card">
										<div class="card-header pt-0 pb-0" id="headingOne">
											<div class="pt-1 float-right">
												<span class="badge badge-primary"> <?=$row['count']?></span>
											</div>
											<h5 class="card-title my-2">
												<a href="#" data-toggle="collapse" data-target="#collapse-<?=$row['id_city']?>" aria-expanded="true" aria-controls="collapseO-<?=$row['id_city']?>"><?=$row['name_city']?>
												</a>
											</h5>
										</div>
										<div id="collapse-<?=$row['id_city']?>" class="collapse" aria-labelledby="headingOne" data-parent="#accordionExample">
											<div class="card-body">
												<div class="row">

$sql = 'SELECT dilery.name_dil, dilery.phone_dil, dilery.email_dil, dilery.site_dil
FROM dilery
INNER JOIN city ON dilery.city_dil = city.id_city
WHERE dilery.city_dil = '.$row['id_city'].' AND dilery.`status` != 1
ORDER BY name_city';

$row_dealers_item = mysqli_query($link,$sql); 
while ($row2 = mysqli_fetch_array($row_dealers_item)) { 
$phone = str_replace(',', '</li><li class="mb-1"><i class="fas fa-phone"></i> ',$row2['phone_dil']); ?>

<div class="col-12 col-lg-6">
															<div class="card mb-3 border">
																<div class="card-header">
																	<h5 class="card-title mb-0"><?=$row2['name_dil']?></h5>
																</div>
																<div class="card-body pt-0">
																	<ul class="list-unstyled mb-0">
																		<?php
																		if(!empty($row2['phone_dil'])) { ?>
																			<li class="mb-1"><i class="fas fa-phone"></i> <?=$phone?>
																		<?php
																		}
																		if(!empty($row2['email_dil'])) { ?>
																			<li class="mb-1"><i class="fas fa-envelope"></i> <a href="mailto:<?=$row2['email_dil']?>"><?=$row2['email_dil']?></a></li>
																		<?php	
																		}
																		if(!empty($row2['site_dil'])) { ?>
																		<li class="mb-1"><i class="fas fa-globe"></i> <a href="https://<?=$row2['site_dil']?>" target="_blank"><?=$row2['site_dil']?></a></li>
																		<?php	
																		}
																		?>
																	</ul>
																</div>
															</div>
														</div>
													<?php
													}
													?>
												</div>
											</div>
										</div>
									</div>
								<?php
								}
								?>
							</div>
  • Вопрос задан
  • 134 просмотра
Пригласить эксперта
Ответы на вопрос 3
Можно применить технику разового чтения главной сущности (аккордеон) постранично, а для сопутствующей информации опрашивать исходя из полученного набора с идентификаторами id.
Select ... from accordions
INNER JOIN city ...
Limit ?, ? /*смещение, количество*/

Select cities.id, ... from dilery
INNER JOIN city ...
Where cities.id in (список получен ранее)

И формируем результат на основе этих двух выборок.
Советую почитать про Шаблон материализованного представления, который предлагает сделать это даже более оптимальным способом.
В сочетании с кэшированием дает хорошие результаты.
Ответ написан
Комментировать
FanatPHP
@FanatPHP
Чебуратор тега РНР
Ну вот опять вопрос высосанный из пальца.
Минимизация количества запросов не долна быть самоцелью.
У тебя играет твой аккордеон? Быстро? Если да - то оставь вего в покое, и ничего не трогай.
Если медленно - то надо ускроить. Но не изменением количества запросов, а ускоренмем того участка, который тупит. Это блин простая истина, но она почему-то недоступна пониманию 95% похапешников. Которые для ускорения работы с сетевыми протоколами кидаются заменять двойные "ковычки" на одинарные.

Менять запросы надо не потому что их много, а потому что они бессмысленные.
Вот у тебя запрос с группировкой, который выводит те же самые данные, что и запрос ниже в цикле.
Вопрос - ЗАЧЕМ тебе этот запрос вообще?
Ну то есть ответ понятен - чтобы можно было кушать любимое спагетти, устравивая кашу из HTML, SQL, CSS, РНР, mysqli, картинок и вообще всего и побольше, главное чтобы всё в куче было.
И как тут в начале страницы узнать, что будет двумя строчками ниже? Загадка века.

А если хотя бы раз в жизни попробовать написать осмысленный код, который сначала получает данные, обрабатывает их, а только потом начинает вывод, то получится, что нужен-то один запрос всего.
Поскольку запросить всех дилеров одним запросом, сгруппировать в массивы по региону и городу, а потом тупо вывести, показывая количество элементов в массиве с помощью банальной функции count(), прекрасно можно и в похапе.

И в итоге не придётся заставлять завсгдатаев тостера напрягать последние извилины для решения таких сложных проблем как "кэширование", "отправка запросов одним запросом" и прочими умными словами, не имеющими ни малейшего отношения к реальности.
Ответ написан
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Собираете все запросы нужных виджетов в стэк и исполняете одним запросом к БД.
Ответ - также разбираете по виджетам в обратном порядке.

Если виджеты публичны - кэшируем периодически результат из БД и отображаем сразу для всех юзеров.

Главное: разделите кэширование на основе ролей.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы