Разбиение большого запроса на два

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
nepster
Сообщения: 838
Зарегистрирован: 2013.01.02, 03:35

Разбиение большого запроса на два

Сообщение nepster »

Моя история такая:

Есть таблица groups:
group_id group_pid group_logo

Есть таблица params:
param_id param_type

И есть связующая таблица (какие параметры к каким группам принадлежат) group_params:
group_id param_id param_order

Необходимо получить все параметры для конкретной группы через таблицу group_params отсортированные по param_order.

Как я понял наболевшая тема, видел варианты на форму. Все усложняется тем, что у меня очень жирный запрос:

Код: Выделить всё

$query = Group::find()
                 ->asArray();

             $query->joinWith([
                 'parent' => function ($query) {
                     $query->from(Group::tableName() . ' pg')
                         ->with([
                             't' => function ($query) {
                             }
                         ]);
                 },
             ]);

             $query->joinWith([
                 'params' => function ($query) {
                     $query->joinWith([
                         'values' => function ($query) {
                             $query->with('t');
                         },
                     ])->with('t');
                 },
             ]);

             $query->with('t')
                 //->status()
                 //->type()
                 ->andWhere(Group::tableName() . '.group_id = :group_id', [':group_id' => $groupId]);
 

Обратите внимание на кол-во реляций и подреляций. Конкретно нас интересуют params.

Код: Выделить всё

    public function getParams()
    {
        return $this->hasMany(Param::className(), ['param_id' => 'param_id'])
            ->viaTable(GroupParams::tableName(), ['group_id' => 'group_id'], function ($query) {
                $query->orderBy(['param_order' => SORT_ASC]);
            });
    } 
К сожалению сортировка внутри viaTable не выдает никаких ошибок и ничего не делает. Поэтому максимум, что я смог сделать, это разбить этот большой запрос на несколько:

Код: Выделить всё

            $result = [];

            $query = Group::find()
                 ->asArray();

             $query->joinWith([
                 'parent' => function ($query) {
                     $query->from(Group::tableName() . ' pg')
                         ->with([
                             't' => function ($query) {
                             }
                         ]);
                 },
             ]);

             $query->with('t')
                 //->status()
                 //->type()
                 ->andWhere(Group::tableName() . '.group_id = :group_id', [':group_id' => $groupId]);

            $result = $query->one();

            if (isset($result['group_id'])) {
                $result['params'] = Param::find()
                    ->asArray()
                    ->select(Param::tableName() . '.*, ' . GroupParams::tableName() . '.param_order')
                    ->innerJoin(GroupParams::tableName(), GroupParams::tableName() . '.param_id=' . Param::tableName() . '.param_id')
                    ->orderBy([GroupParams::tableName() . '.param_order' => SORT_ASC])
                    ->where(GroupParams::tableName() . '.group_id = '.$result['group_id'])
                    ->joinWith([
                        'values' => function ($query) {
                            $query->with('t');
                        },
                    ])->with('t')
                    ->all();                
            }
 
Все конечно работает, но меня не покидает странное ощущение кривожопости 2 запросов.

Вопрос такой, если будет форс-мажор, лаганет сервер или база, или еще что. Какие могут вообще быть последствия в таком подходе ?
Аватара пользователя
irpsv
Сообщения: 65
Зарегистрирован: 2015.07.07, 18:03
Контактная информация:

Re: Разбиение большого запроса на два

Сообщение irpsv »

Заметил что многие господа с сущностными БД кроме как таблица вообще не знакомы. Вы знаете что такое VIEW в рамках БД? Проще в нее засунуть весь сложный запрос, а из PHP обращаться сразу в VIEW без монструозных строк кода. Нет?

http://www.sql.ru/docs/sql/u_sql/ch20.shtml
...то что мы не понимаем, делает нас тупее...
Аватара пользователя
vitalik1183
Сообщения: 1675
Зарегистрирован: 2014.07.01, 08:42

Re: Разбиение большого запроса на два

Сообщение vitalik1183 »

Кроме как кол-во и упрощения кода это не даст никаких преимуществ в данной ситуации.

В чем профит представления конкретно здесь? Там выполняется точно такой же запрос только изолировано. Как то поднимал я тему насчет дата провайдеров и представлений. Разве что получается что запрос на каунт становится тривиальным, а больше особого профита нет.
Yii2!
Аватара пользователя
irpsv
Сообщения: 65
Зарегистрирован: 2015.07.07, 18:03
Контактная информация:

Re: Разбиение большого запроса на два

Сообщение irpsv »

vitalik1183 писал(а):Кроме как кол-во и упрощения кода это не даст никаких преимуществ в данной ситуации.

В чем профит представления конкретно здесь? Там выполняется точно такой же запрос только изолировано. Как то поднимал я тему насчет дата провайдеров и представлений. Разве что получается что запрос на каунт становится тривиальным, а больше особого профита нет.
А что именно в данной ситуации даст преимущество? НИЧЕГО! Тут скорее дело выбора, кому прикольно лепить такую херабасину на PHP - успехов и удачи в будущем, пригодиться, крайне.
...то что мы не понимаем, делает нас тупее...
Аватара пользователя
vitalik1183
Сообщения: 1675
Зарегистрирован: 2014.07.01, 08:42

Re: Разбиение большого запроса на два

Сообщение vitalik1183 »

А что именно в данной ситуации даст преимущество? НИЧЕГО! Тут скорее дело выбора, кому прикольно лепить такую херабасину на PHP - успехов и удачи в будущем, пригодиться, крайне.
Ну вообще не вижу ничего страшного. Т.е. по вашему сча будем на каждый сложный запрос лепить представление и отдельную модель? Ну с точки зрения восприятия ессно это лучше и кода меньше, но а если например запрос формируется динамически или зависит от иных факторов, таких как роль пользователя или день недели?

Вопщем представления это только дело вкуса, никаких особых преимуществ они не дают.
Yii2!
Аватара пользователя
irpsv
Сообщения: 65
Зарегистрирован: 2015.07.07, 18:03
Контактная информация:

Re: Разбиение большого запроса на два

Сообщение irpsv »

vitalik1183 писал(а):но а если например запрос формируется динамически или зависит от иных факторов, таких как роль пользователя или день недели?
1. Каким образом запрос может формироваться динамически?
2. А в чем разница кодом обратиться к таблице или через представление, в плане роль пользователя или день недели? Для условий есть конструкция WHERE

Такое подозрения, что вы тоже не совсем знакомы со вьюхами
...то что мы не понимаем, делает нас тупее...
Аватара пользователя
vitalik1183
Сообщения: 1675
Зарегистрирован: 2014.07.01, 08:42

Re: Разбиение большого запроса на два

Сообщение vitalik1183 »

1. Каким образом запрос может формироваться динамически?
Композитный фильтр или выборка как минимум, например у меня в одной системе есть выборка по идентификаторам, и в зависимости от роли запрос может быть довольно различным.
2. А в чем разница кодом обратиться к таблице или через представление, в плане роль пользователя или день недели? Для условий есть конструкция WHERE
Есть то есть, но например окончательный результат может зависеть от кучи других факторов. Например, мне нужно выбрать юзеров, которые совершили покупки более чем на 5 тысяч рублей, как вы собрались динамически пихать хевинг в представление?
Такое подозрения, что вы тоже не совсем знакомы со вьюхами
Ой ипать какие мы тут пришли важные и сверх умные. Иди уроки учи школьник.
Yii2!
Аватара пользователя
irpsv
Сообщения: 65
Зарегистрирован: 2015.07.07, 18:03
Контактная информация:

Re: Разбиение большого запроса на два

Сообщение irpsv »

vitalik1183 писал(а):Композитный фильтр или выборка как минимум, например у меня в одной системе есть выборка по идентификаторам, и в зависимости от роли запрос может быть довольно различным.
В представление по сути должен быть первичный ключ, то есть ID (вот ссылка на всякий случай, а то мало ли, не знаю всех ваших познаний http://www.w3schools.com/sql/sql_primarykey.asp), что мешает в WHERE прописать все эти ID (и по сути, PHP кодом, вы сделаете ровно тоже самое). Нет?
vitalik1183 писал(а):Есть то есть, но например окончательный результат может зависеть от кучи других факторов. Например, мне нужно выбрать юзеров, которые совершили покупки более чем на 5 тысяч рублей, как вы собрались динамически пихать хевинг в представление?

Код: Выделить всё

SELECT id_user, SUM(cost) FROM view GROUP BY id_user HAVING SUM(cost) > 5000
Все таки лучше сначала прочитать что такое VIEW, а то ты все больше и больше дебил. VIEW (если простенько) это запрос к которому можно обратиться, как к таблице.
vitalik1183 писал(а):Ой ипать какие мы тут пришли важные и сверх умные. Иди уроки учи школьник.
Ну пока что ты себя ведешь как тупой школьник и ничего дельного не пишешь. Да и по манере написания понятно что ты такое.

Не в тему, но все же: вообще забавляют чмошные задроты которые на форумах выебывается, а из себя ... ничего не представляют! Грустно все это.
...то что мы не понимаем, делает нас тупее...
Аватара пользователя
vitalik1183
Сообщения: 1675
Зарегистрирован: 2014.07.01, 08:42

Re: Разбиение большого запроса на два

Сообщение vitalik1183 »

Все таки лучше сначала прочитать что такое VIEW, а то ты все больше и больше дебил. VIEW (если простенько) это запрос к которому можно обратиться, как к таблице.
дак это понятно, вопрос в том что предварительно то будет выполнен основной запрос.

Чувкак, иди реально нахер, ты тут пишешь ниачем и вапще не в тему дела. ТС спросил а ты какую то воду льешь про вьюхи. О да, сча введем вьюхи и все залетает.
Yii2!
Аватара пользователя
irpsv
Сообщения: 65
Зарегистрирован: 2015.07.07, 18:03
Контактная информация:

Re: Разбиение большого запроса на два

Сообщение irpsv »

vitalik1183 писал(а):
Все таки лучше сначала прочитать что такое VIEW, а то ты все больше и больше дебил. VIEW (если простенько) это запрос к которому можно обратиться, как к таблице.
дак это понятно, вопрос в том что предварительно то будет выполнен основной запрос.
А ты уверен что планировщик просто не допишет условие к основному запросу, прежде чем выполнить его?
vitalik1183 писал(а):Чувкак, иди реально нахер, ты тут пишешь ниачем и вапще не в тему дела. ТС спросил а ты какую то воду льешь про вьюхи. О да, сча введем вьюхи и все залетает.
По кнопкам не попадаешь, нервничаешь что ли?))) Ты же можешь просто не отвечать, не пробовал? Но по сути ты прав: развели холивар.
...то что мы не понимаем, делает нас тупее...
Аватара пользователя
vitalik1183
Сообщения: 1675
Зарегистрирован: 2014.07.01, 08:42

Re: Разбиение большого запроса на два

Сообщение vitalik1183 »

А ты уверен что планировщик просто не допишет условие к основному запросу, прежде чем выполнить его?
Факты представь, свои слова заберу обратно.
По кнопкам не попадаешь, нервничаешь что ли?))) Ты же можешь просто не отвечать, не пробовал? Но по сути ты прав: развели холивар.
В личке я тебе ответил куда пойти, собсно в баньку попариться веничком и испить холодного кваса.
Yii2!
Аватара пользователя
irpsv
Сообщения: 65
Зарегистрирован: 2015.07.07, 18:03
Контактная информация:

Re: Разбиение большого запроса на два

Сообщение irpsv »

vitalik1183 писал(а):
А ты уверен что планировщик просто не допишет условие к основному запросу, прежде чем выполнить его?
Факты представь, свои слова заберу обратно.
Сначала хотел накидать литературы полезной, а потом вспомнил про замечательный EXPLAIN. И так исходные данные:

Имеется представление:

Код: Выделить всё

SELECT user.*, attribute_anketa.*
FROM `user` JOIN `attribute_anketa` ON `user`.`id` = `attribute_anketa`.`id_user`
WHERE `attribute_anketa`.`gonorar` > 10000
Таблицы:
  • user(id,username,password)
  • attribute_anketa(id_user,id_nation,gonorar,weight)
В прикреплениях соответственно запросы и планы для них. По ним видно что при добавлении условия просто сменился тип выборки и ключ по которому выбираются значения. А запрос все также один! На самом деле здесь не показаны низкоуровневые команды (как к примеру можно посмотреть в SQLite если не ошибаюсь), но в любом случае видно что один запрос.

Если использовать GROUP BY то создается временная таблица и делается дополнительный проход для сортировки (тоже ниже во вложениях exp3.png).

Если непонятно что к чему, то вот про EXPLAIN: http://www.mysql.ru/docs/man/EXPLAIN.html

Жду реверса)))
Вложения
explain select * from test group by id_user
explain select * from test group by id_user
exp3.png (5.95 КБ) 4563 просмотра
EXPLAIN SELECT * FROM test WHERE username LIKE "rpsv"
EXPLAIN SELECT * FROM test WHERE username LIKE "rpsv"
exp2.png (5.84 КБ) 4563 просмотра
EXPLAIN SELECT * FROM
EXPLAIN SELECT * FROM
exp1.png (5.55 КБ) 4563 просмотра
...то что мы не понимаем, делает нас тупее...
Аватара пользователя
vitalik1183
Сообщения: 1675
Зарегистрирован: 2014.07.01, 08:42

Re: Разбиение большого запроса на два

Сообщение vitalik1183 »

все круто, но где здесь представление?
Yii2!
Аватара пользователя
irpsv
Сообщения: 65
Зарегистрирован: 2015.07.07, 18:03
Контактная информация:

Re: Разбиение большого запроса на два

Сообщение irpsv »

vitalik1183 писал(а):все круто, но где здесь представление?
К которой обращаются test. Код такой:

Код: Выделить всё

CREATE VIEW `test` AS
SELECT user.*, attribute_anketa.*
FROM `user` JOIN `attribute_anketa` ON `user`.`id` = `attribute_anketa`.`id_user`
WHERE `attribute_anketa`.`gonorar` > 10000
Забыл указать что это представление)
...то что мы не понимаем, делает нас тупее...
Аватара пользователя
vitalik1183
Сообщения: 1675
Зарегистрирован: 2014.07.01, 08:42

Re: Разбиение большого запроса на два

Сообщение vitalik1183 »

эксплайн представления предоставь друг мой
Yii2!
Ответить