SELECT WHERE IN: Подскажите оптимальный вариант взаимодействия PHP — MySQL

Здравствуйте.

Как сделать правильней, как сделать оптимальней?

1 вариант:

Получаем результат первого запроса:
SELECT `ID` FROM `TABLE_A`WHERE `FIELD_C` = '123';

Подставляем рез-т первого запроса во второй запрос:
SELECT * FROM `TABLE_B` WHERE `FIELD_A` IN ('результат 1-ого запроса');

Итого транзакций: 2
Возникает вопрос: а если результатом первого запроса будет 1k идентификаторов?

2 вариант:

SELECT * FROM `TABLE_B` WHERE `FIELD_A` IN (SELECT `ID` FROM `TABLE_A`WHERE `FIELD_C` = '123');

Итого транзакций: 1
Возникает вопрос: не является ли этот запрос сложным?

Смысл моего вопрос в следующем: в статьях про архитектуру высоконагруженных систем (например, таких как twitter) рекомендуется при взаимодействии с БД использовать простые запросы, а формирование результата проводить на вычислительных серверах (их проще масштабировать).
Так вот, что лучше:
— 1 вариант с двумя простыми запросами к БД, но, возможно, сложным для разбора вторым запросом, если кол-во передаваемых идентификаторов, например тысяча?
— 2 вариант с одним запросом, но вложенным?

Спасибо за ответы!
  • Вопрос задан
  • 26390 просмотров
Пригласить эксперта
Ответы на вопрос 8
@shagguboy
>в статьях про архитектуру высоконагруженных систем (например, таких как twitter)
пока у вас нет нагрузок как у Твиттера, не делайте так. только усложните себе жизнь, написанием своих собственных джойнов на php
Ответ написан
Комментировать
@shagguboy
лично я за inner joib потому что in (до версии 6 точно) оптимизируется как depend subquery.
Ответ написан
Если таблицы однотипные (это касается и полей, и движков) и не используется (не эффективно) кэширование, то лучше 2 вариант.
В остальных случаях 1 вариант.
Ответ написан
taliban
@taliban
php программист
Вообще, если уж начали про архитекруту, то просто сделайте так:
tableB->getAll();
Как внутри все будет работать пока что Вас не должно волновать, главное чтоб этот метод (функция) возвращала _всегда_ одни и те же данные. Потом когда (если?) будет тормозить, или Вас будет что-то не устраивать Вы этот метод переделаете как душа пожелает.
Так что не важно что именно вы сделаете, главное выделяйте такие спорные вопросы в одном месте, которое _всегда_ возвращает одни и те же данные, как бы Вы его не меняли.
Ответ написан
Комментировать
@egorinsk
Если выбрать второй вариант, нельзя будет сделать дешевую оптимизацию разнесением таблиц на разные сервера. То есть в этом случае с ростом нагрузки придется покупать массивы дисков, многопроцессорные ядра и прочую хрень. А потом ломать руки архитектору и переписывать весь код.

А в первом случае банально разносим таблицы по серверам и еще годик бездельничаем.

Также, с первым вариантом, сущности можно дергать частично из кеша мультизапросом. А второй вариант хрен закешируешь.

Так что не слушайте джойнеров, потом жалеть будете.
Ответ написан
png
@png
Я за вариант 2. если нет варианта 3.
Вариант 1 может иногда не работать из-за попадания на лимиты:

можно попасть на 2 лимита
1. превышение максимальной длины запроса
2. превышение максимального количества параметров в IN. да, там тоже есть ограничения

Ограничения есть не только в мускуле, но и в оракле, постргессе и других БД.

Вариант 2 ещё к тому же и тормознутый, если у нас много записей во внешнем запросе.

Простые запросы будут работать быстрее:
select * from table1,table2 where условия
или запрос через
join
select * from table1 join table2 on условие where условия

какие из них, будет работать быстрее смотрите сами. Настройки БД подпиливаются под данные и под запросы, которые будут исполняться на этих данных.
Ответ написан
Комментировать
@gro
>а если результатом первого запроса будет 1k идентификаторов?
а проверить что же будет?
Ответ написан
Комментировать
Цель таких оптимизаций — это сделать так, чтобы база делала как можно меньше, а приложение, которое работает с базой, как можно больше. Ведь базу трудно масштабировать, а серверов, на которых крутится приложение, добавить легко.

Если у вас один сервер под приложение и под базу, то такая оптимизация вредна, потому что приложение не сделает быстрее то, что сделает база в большинстве случаев. Поэтому надо использовать inner join.

Если Вы интересуетесь из академических соображений или уже готовы к закупкам новых серверов, то первый вариант лучше.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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