Дочерние таблицы. Оптимизация запросов.

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
de11et
Сообщения: 9
Зарегистрирован: 2017.04.26, 18:47

Дочерние таблицы. Оптимизация запросов.

Сообщение de11et »

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

Структура моей БД такова: имеется родительская таблица Table_1 и две дочерние TableValue_1 и TableValue_2.

Эти две дочерние таблицы ссылаются на поле id родительской.

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

Мой вопрос заключается в SQL запросах, которые выполняет Yii2:

SELECT * FROM `TableValue_1` WHERE `table_id` IN ('1', '2', '3', '4', '5')
SELECT * FROM `TableValue_2` WHERE `table_id` IN ('1', '2', '3', '4', '5')

Здесь наблюдается избыточность в запросах, ведь на самом деле в БД поле TableValue_1. table_id содержит только значения: 1, 2, 3. А поле TableValue_2. table_id содержит: 4, 5.

Что нужно сделать, чтобы в результате выполнялись примерно такие запросы (которые не будут содержать избыточных данных):

SELECT * FROM `TableValue_1` WHERE `table_id` IN ('1', '2', '3')
SELECT * FROM `TableValue_2` WHERE `table_id` IN ('4', '5')

Заранее благодарю.
Аватара пользователя
rodion_zlobin
Сообщения: 207
Зарегистрирован: 2017.01.11, 16:33

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение rodion_zlobin »

А вы по какому принципу делите? Если в лоб — прописывайте select from tv1 where table_id => 3 и select from tv2 where table_id < 3
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение caHek2x »

покажите как вы прописали связи ...
Аватара пользователя
SiZE
Сообщения: 2817
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение SiZE »

de11et, это жадная загрузка. все ок
de11et
Сообщения: 9
Зарегистрирован: 2017.04.26, 18:47

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение de11et »

Всем спасибо за помощь.

Файлы (контроллеры, модели, дамп БД ...) доступны по ссылке: https://yadi.sk/d/2ZJPILul3HsfyR

Планируется в главной таблице Table хранить множество записей, часть из которых будет связана с TableValue_1, а другая часть с TableValue_2. При этом естественно таблица Table будет постоянно пополняться новыми данными (ну типа написал статью - сохранил в БД).

Хотелось бы не иметь избыточности в SQL запросах (например, из 10000 записей будет 3000 холостых, а это не хорошо), но при этом нормально использовать связи моделей Yii2 (т.е. без всяких костылей). В любом случае приветствуются любые решения. Спасибо.
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение caHek2x »

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

public function getTableValue1() {
        return $this->hasOne(TableValue1::className(), ['table_id' => 'id']);
    }

    public function getTableValue2() {
        return $this->hasOne(TableValue2::className(), ['table_id' => 'id']);
    }
ну конечно ... у вас связи ничем не отличаются ... в чем разница между ними ? как программе понять что это к той таблице а это к той ?
de11et
Сообщения: 9
Зарегистрирован: 2017.04.26, 18:47

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение de11et »

caHek2x, не совсем понимаю. Почему не отличаются, названия геттеров и модели ведь разные и как это решает проблему?
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение caHek2x »

название и модели ... эм а условие где отличается ?
условие одно и тоже вот и запрос выходит ('1', '2', '3', '4', '5')
откуда алгоритм должен знать что в одну ('1', '2', '3') а в другую ('4', '5')
de11et
Сообщения: 9
Зарегистрирован: 2017.04.26, 18:47

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение de11et »

Не подскажете рабочий вариант? Но также учитывая то, что, например, в поле TableValue_2. table_id порядок значений будет не как сейчас: '4', '5', а хаотичный, т.е. '4', '5', '8', '10', '17', '21' и т.д.
Maxxi
Сообщения: 29
Зарегистрирован: 2014.11.20, 22:39

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение Maxxi »

de11et писал(а): 2017.05.08, 20:27
SELECT * FROM `TableValue_1` WHERE `table_id` IN ('1', '2', '3', '4', '5')
SELECT * FROM `TableValue_2` WHERE `table_id` IN ('1', '2', '3', '4', '5')

Здесь наблюдается избыточность в запросах, ведь на самом деле в БД поле TableValue_1. table_id содержит только значения: 1, 2, 3. А поле TableValue_2. table_id содержит: 4, 5.
Здесь нет никакой избыточности. Запросы выбирают ровно те данные, которые запросили.
Невозможно до выполнения запроса узнать какие table_id содержат связанные таблицы.
На самом деле, это эмуляция обычного LEFT JOIN. Сначала выбираются все записи из главной таблицы, а потом по table_id выбираются подчиненные.
de11et
Сообщения: 9
Зарегистрирован: 2017.04.26, 18:47

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение de11et »

Maxxi, если будет много записей и Yii2 выдаст такой запрос:

SELECT * FROM `TableValue_1` WHERE `table_id` IN ('1', '2', '3', '4', '5'...'10000') из которых, скажем, 2000 значений на самом деле соответствуют id гл.табл., а остальные 8000 нет. Это разве не будет влиять на производительность? Есть ли альтернативные способы? И что насчёт варианта, который предложил caHek2x?
Maxxi
Сообщения: 29
Зарегистрирован: 2014.11.20, 22:39

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение Maxxi »

de11et писал(а): 2017.05.09, 16:15 Maxxi, если будет много записей и Yii2 выдаст такой запрос:

SELECT * FROM `TableValue_1` WHERE `table_id` IN ('1', '2', '3', '4', '5'...'10000') из которых, скажем, 2000 значений на самом деле соответствуют id гл.табл., а остальные 8000 нет. Это разве не будет влиять на производительность? Есть ли альтернативные способы? И что насчёт варианта, который предложил caHek2x?
это легко проверить следующим примером

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

        $querry = Table::findAll([1,3,5])
        ->with('tableValue1','tableValue2')
        ->asArray()
        ->all();
p.s. querry не стал исправлять, чтоб путаницы не было
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение caHek2x »

de11et писал(а): 2017.05.09, 16:15 И что насчёт варианта, который предложил caHek2x?
я предложил какойто вариант ? Оо
я вам указал что у вас в обоих связях одно и тоже условие ...
вы или принцип не понимаете или не знаете чего вы хотите ...
у вас в одной таблице цвет .. .в другой размер .. .ок ...
сделайте в таблице Table_1 столбцы color_id и size_id ... а в TableValue_1/2 будет только id и value ...
Maxxi
Сообщения: 29
Зарегистрирован: 2014.11.20, 22:39

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение Maxxi »

caHek2x писал(а): 2017.05.09, 16:21 я вам указал что у вас в обоих связях одно и тоже условие ...
вы или принцип не понимаете или не знаете чего вы хотите ...
у вас в одной таблице цвет .. .в другой размер .. .ок ...
сделайте в таблице Table_1 столбцы color_id и size_id ... а в TableValue_1/2 будет только id и value ...
Условия правильные написаны.
Вопрос организации данных здесь вроде не поднимался. Это уже другая тема.
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение caHek2x »

исходя из того что ТС предполагает что из за разности названий и моделей в связи должен формироваться разный sql я выразил мысль о его непонимании или принципа или неверной структуре ... а он уже пусть делает выводы ...
de11et
Сообщения: 9
Зарегистрирован: 2017.04.26, 18:47

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение de11et »

caHek2x писал(а): 2017.05.09, 16:21 сделайте в таблице Table_1 столбцы color_id и size_id ... а в TableValue_1/2 будет только id и value ...
Это уже лучше. В этом случае, конечно, будет много пустых значений для тех строк, которые не имеют в поле color_id соответствующих значений и также наоборот для size_id. Но по мне так это меньшее из зол.
Аватара пользователя
SiZE
Сообщения: 2817
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение SiZE »

de11et писал(а): 2017.05.09, 16:152000 значений на самом деле соответствуют id гл.табл., а остальные 8000 нет
Мягко говоря AR не для того чтобы ворочать по 10 000 записей. Памяти тупо не хватит. Во вторых, если хочется достать за один раз 10 000 записей, то надо хорошенько призадуматься.
de11et
Сообщения: 9
Зарегистрирован: 2017.04.26, 18:47

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение de11et »

Ясно. Тогда, полагаю, при работе с большим количеством записей в AR нужно использовать "Пакетное получение данных (batch(), each())"?
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение caHek2x »

я когда достаю слишком много данных то работаю через asArray, чтоб не создавались обьекты а просто голые данные ... но опять же все от ситуации зависит ...
Аватара пользователя
SiZE
Сообщения: 2817
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Дочерние таблицы. Оптимизация запросов.

Сообщение SiZE »

de11et писал(а): 2017.05.10, 08:48 Ясно. Тогда, полагаю, при работе с большим количеством записей в AR нужно использовать "Пакетное получение данных (batch(), each())"?
Как вариант. Только каменты почитай еще если будут проблемы http://rmcreative.ru/blog/post/yii2-batch Я предпочитаю через Query это делать примерно так:

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

$query = new Query();
// ... build query
$offset = 0;
$batchSize = 100;
$query->limit($batchSize);
while ($batch = $query->offset($offset)->all()) {
   $offset += $batchSize;
   foreach ($batch as $row) {
   }
}
Закрыто