Mysql Запрос по 3ем таблицам

godunreal

Новичок
Есть 3 таблицы

1ая - history:
id, user, group, type, object, time, status
В ней хранится "история", где user - id пользователя, у которого произошло событие
group - id группы, у которой произошло событие (к примеру, публикация записи)
Причем, либо user, либо group равняется "0", т.к. событие не можем происходить одновременно у группы и пользователя.

2ая таблица friends:
id, with, status, time
здесь id и with - id пользователей, которые "дружат" друг с другом при status = 1

3ая таблица members_group (участники групп):
user, group, time, level
здесь user - id пользователя, group - id группы, в которой user состоит.

Есть следующий запрос.

Код:
SELECT history.type,history.object,history.group AS hgroup,history.time,history.id,history.status,history.user AS huser ,friends.id,friends.with,members_group.user,members_group.group FROM history,friends,members_group WHERE
(((friends.id=history.user OR friends.with=history.user) AND ((friends.id=$check_session[id] OR friends.with=$check_session[id] AND friends.active=1) OR (friends.id=$check_session[id])))
OR
(history.group=members_group.group AND members_group.user=$check_session[id] AND history.type='group_wall'))
AND history.status=1
GROUP BY history.id ORDER BY history.time DESC
LIMIT $begin_user,10
Данные он выводит верно. Все замечательно. Кроме одного.
Запрос выполняется очень долго... php зависает на несколько минут после выполнения запроса.

Можете помочь оптимизировать запрос и подсказать, что делать?

Пробовал перестроить запрос с INNER JOIN для оптимизации с ключами - не получилось составить сам запрос...

Буду безумно благодарен за помощь!
 

riff

Новичок
Во-первых, ускорить сможешь, выбрав в начале
Код:
SELECT id FROM history
WHERE history.user = $check_session[id] AND history.status=1
ORDER BY history.time DESC
LIMIT $begin_user,10
Это для того, чтобы не заставлять mysql объединять не участвующие в итоговом результате строки.

Затем, в своём запросе, вместо
GROUP BY history.id
LIMIT $begin_user,10
подставить
Код:
AND history.id in (ids_из_пред_запроса)
Во-вторых, По-моему твой sql явно требует разделить его на две логические части: select history-friends и select hystory-groups.
Выбираешь по отдельности (не забываем про вышесказанное), объединяем два массива и сортируем по тайму.

Это то, что мне, на вскидку, пришло в голову, возможно что-то упустил из виду.
 
Последнее редактирование:

godunreal

Новичок
Во-первых, ускорить сможешь, выбрав в начале
Код:
SELECT id FROM history
WHERE history.user = $check_session[id] AND history.status=1
ORDER BY history.time DESC
LIMIT $begin_user,10
Это для того, чтобы не заставлять mysql объединять не участвующие в итоговом результате строки.

Затем, в своём запросе, вместо


подставить
Код:
AND history.id in (ids_из_пред_запроса)
Во-вторых, По-моему твой sql явно требует разделить его на две логические части: select history-friends и select hystory-groups.
Выбираешь по отдельности (не забываем про вышесказанное), объединяем два массива и сортируем по тайму.

Это то, что мне, на вскидку, пришло в голову, возможно что-то упустил из виду.
Замечательно!
Я забыл про "in()". Натолкнули на хорошую мысль!

Составил 2 простых запроса для сохранения ID'шников у friends & members_group
и вставил их в in() в сам запрос, упростив его до "простого" запроса.

Скорость загрузки составляет теперь 0.0094 сек. вместо 84 сек. :-]

Спасибо огромное!
 
Сверху