Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Уменьшение количества MySQL запросов 
:(
    Опции темы
Ramoff
Дата 25.12.2012, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 25.12.2012

Репутация: нет
Всего: нет



Всем привет)

Есть у меня таблица в базе MySQL с 1600 записей типа:
ID | name | surname | price | good | quantity

Выполняется скрипт PHP, который должен вывести таблицу с анализом по каждому клиенту типа (я схематично опишу):
Код

$sql_01 = mysq_query("SELECT * FROM `table` where 1 GROUP BY `good`");
while ($line_01 = mysql_fetch_array($sql_01)) {
     /* Тут код какой-то. Вывод данные на экран или запись в переменную ... Не суть, в общем. */
     
     // А вот тут мы хотим посмотреть по данному товару: кто покупал.
     $sql2 = mysq_query("SELECT * FROM `table` WHERE `good`='".$line_01['good']."'");
     while ($line_02 = mysql_fetch_array($sql_02)) {
          /* Тут код какой-то. Вывод данные на экран или запись в переменную ... Не суть, в общем. */
     }
}


Из-за того, что, собственно, данных много, а в таблице полей порядка сотни на самом деле, а записей порядка 1 600 штук, то при уровне вложенности таких запросов получается порядка 600 MySQL запросов. Естесственно, что это ведёт к повышенному потреблению RAM (до 25 мегов в пике) и процессора. Пусть сервер и мощный, но всегда надо стараться всё оптимизировать.

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

Буду рад любым комментариям.

Добавлено через 7 минут и 50 секунд
А что самое интересное — время работы скрипта может варьироваться от 0,4 секунды до 70.

Добавлено через 10 минут и 31 секунду
А может ли влиять на время обработки влиять наличие индекса полнотекстового у таблицы на часто используемые поля?
PM MAIL   Вверх
Aliance
Дата 25.12.2012, 18:21 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


I ♥ <script>
****


Профиль
Группа: Модератор
Сообщений: 6418
Регистрация: 2.8.2004
Где: spb

Репутация: 3
Всего: 137



Во-первых, все запросы нужно анализировать с помощью EXPLAIN и смотреть, юзается ли индекс.

Тут не совсем понятно вот что: `table` в обоих запросах одна и та же? Если нет - можно объединить запросы в один через left join. Если одна и та же, то получается фактически второй запрос выбирает все данные по товару в цикле всех товаров (то есть все данные всех товаров). А значит его можно выполнить один раз за пределами цикла и дальше обращаться к static cached данным.
PM MAIL WWW ICQ Skype   Вверх
Ramoff
Дата 25.12.2012, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 25.12.2012

Репутация: нет
Всего: нет



Aliance, по EXPLAIN я сейчас буду изучать.

`table` — действительно везде одна и та же. И в конце запроса первого самого стоит GROUP, чтобы исключить вывод повторяющихся данных. А это значит, что не получится избежать второго цикла, где происходит как раз уточнение данных первого запроса...
PM MAIL   Вверх
Aliance
Дата 25.12.2012, 19:06 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


I ♥ <script>
****


Профиль
Группа: Модератор
Сообщений: 6418
Регистрация: 2.8.2004
Где: spb

Репутация: 3
Всего: 137



По факту получается, что первым запросом ты получаешь массив уникальный GOOD_ID, а во втором запросе по каждому отдельно получаешь. Что мешает сделать два цикла. Первый запрос - заполняем массив $good_ids = array() этими значениями, второй цикл - по результатам запроса №2, только с условием good IN(ID1, ID3, ID3)
PM MAIL WWW ICQ Skype   Вверх
Ramoff
Дата 25.12.2012, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 25.12.2012

Репутация: нет
Всего: нет



Aliance, а можно небольшой пример абстрактный? Я почему-то "догнать" не могу этот метод.
PM MAIL   Вверх
Arantir
Дата 25.12.2012, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: нет
Всего: 55



Ramoff, я бы вообще предложил сначала выбрать все нужные данные  (которые вы для каждого good выбираете) через
Код

SELECT fileld1, field2, ... FROM `table` ORDER BY `good`
а уже потом получить список good вашим первым запросом, но данные для них выбирать из resultset-а полученного вышеприведенным запросом. Разница в том, что вы будете вместо запроса осуществлять поиск в локальной переменной (массиве).
Это сократит все до 2-х запросов. Да, конечно, придется сразу держать много данных, но это все же эффективнее за 600 запросов.
Об этом, собственно, Aliance, выше писал.

К вышесказанному: Выберите все данные вышеприведенным запросом, потом в цикле поместите все строки в массив.
После чего дальше вы сможете выбирать для каждого good его строки просто сравнивая в цикле $array[i]['good'] массива всех строк с текущим good. Кроме того, массив отсотрирован, так что, после первого попавшегося подходящего good, следующий неподходящий означает, что подходящих больше нет и цикл текущего good можно завершать, сократив таким образом количество операций.
При желании для всего этого можно даже написать бинарный поиск, только надо предусмотреть множественность результатов поиска.

Это сообщение отредактировал(а) Arantir - 25.12.2012, 22:45


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
Ramoff
Дата 25.12.2012, 22:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 25.12.2012

Репутация: нет
Всего: нет



Arantir, теперь всё стало ясно! Спасибо большое! Сейчас буду экспериментировать! Хотя до последнего надеялся, что можно сформировать какой-то сложный MySQL запрос. Но и это неплохо.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Базы Данных | Следующая тема »


 




[ Время генерации скрипта: 0.0446 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.