Дочерние таблицы. Оптимизация запросов.
Дочерние таблицы. Оптимизация запросов.
Здравствуйте.
Структура моей БД такова: имеется родительская таблица 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')
Заранее благодарю.
Структура моей БД такова: имеется родительская таблица 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: Дочерние таблицы. Оптимизация запросов.
А вы по какому принципу делите? Если в лоб — прописывайте select from tv1 where table_id => 3 и select from tv2 where table_id < 3
Re: Дочерние таблицы. Оптимизация запросов.
покажите как вы прописали связи ...
Re: Дочерние таблицы. Оптимизация запросов.
de11et, это жадная загрузка. все ок
Re: Дочерние таблицы. Оптимизация запросов.
Всем спасибо за помощь.
Файлы (контроллеры, модели, дамп БД ...) доступны по ссылке: https://yadi.sk/d/2ZJPILul3HsfyR
Планируется в главной таблице Table хранить множество записей, часть из которых будет связана с TableValue_1, а другая часть с TableValue_2. При этом естественно таблица Table будет постоянно пополняться новыми данными (ну типа написал статью - сохранил в БД).
Хотелось бы не иметь избыточности в SQL запросах (например, из 10000 записей будет 3000 холостых, а это не хорошо), но при этом нормально использовать связи моделей Yii2 (т.е. без всяких костылей). В любом случае приветствуются любые решения. Спасибо.
Файлы (контроллеры, модели, дамп БД ...) доступны по ссылке: https://yadi.sk/d/2ZJPILul3HsfyR
Планируется в главной таблице Table хранить множество записей, часть из которых будет связана с TableValue_1, а другая часть с TableValue_2. При этом естественно таблица Table будет постоянно пополняться новыми данными (ну типа написал статью - сохранил в БД).
Хотелось бы не иметь избыточности в SQL запросах (например, из 10000 записей будет 3000 холостых, а это не хорошо), но при этом нормально использовать связи моделей Yii2 (т.е. без всяких костылей). В любом случае приветствуются любые решения. Спасибо.
Re: Дочерние таблицы. Оптимизация запросов.
Код: Выделить всё
public function getTableValue1() {
return $this->hasOne(TableValue1::className(), ['table_id' => 'id']);
}
public function getTableValue2() {
return $this->hasOne(TableValue2::className(), ['table_id' => 'id']);
}
Re: Дочерние таблицы. Оптимизация запросов.
caHek2x, не совсем понимаю. Почему не отличаются, названия геттеров и модели ведь разные и как это решает проблему?
Re: Дочерние таблицы. Оптимизация запросов.
название и модели ... эм а условие где отличается ?
условие одно и тоже вот и запрос выходит ('1', '2', '3', '4', '5')
откуда алгоритм должен знать что в одну ('1', '2', '3') а в другую ('4', '5')
условие одно и тоже вот и запрос выходит ('1', '2', '3', '4', '5')
откуда алгоритм должен знать что в одну ('1', '2', '3') а в другую ('4', '5')
Re: Дочерние таблицы. Оптимизация запросов.
Не подскажете рабочий вариант? Но также учитывая то, что, например, в поле TableValue_2. table_id порядок значений будет не как сейчас: '4', '5', а хаотичный, т.е. '4', '5', '8', '10', '17', '21' и т.д.
Re: Дочерние таблицы. Оптимизация запросов.
Здесь нет никакой избыточности. Запросы выбирают ровно те данные, которые запросили.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 выбираются подчиненные.
Re: Дочерние таблицы. Оптимизация запросов.
Maxxi, если будет много записей и Yii2 выдаст такой запрос:
SELECT * FROM `TableValue_1` WHERE `table_id` IN ('1', '2', '3', '4', '5'...'10000') из которых, скажем, 2000 значений на самом деле соответствуют id гл.табл., а остальные 8000 нет. Это разве не будет влиять на производительность? Есть ли альтернативные способы? И что насчёт варианта, который предложил caHek2x?
SELECT * FROM `TableValue_1` WHERE `table_id` IN ('1', '2', '3', '4', '5'...'10000') из которых, скажем, 2000 значений на самом деле соответствуют id гл.табл., а остальные 8000 нет. Это разве не будет влиять на производительность? Есть ли альтернативные способы? И что насчёт варианта, который предложил caHek2x?
Re: Дочерние таблицы. Оптимизация запросов.
это легко проверить следующим примером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();
Re: Дочерние таблицы. Оптимизация запросов.
я предложил какойто вариант ? Оо
я вам указал что у вас в обоих связях одно и тоже условие ...
вы или принцип не понимаете или не знаете чего вы хотите ...
у вас в одной таблице цвет .. .в другой размер .. .ок ...
сделайте в таблице Table_1 столбцы color_id и size_id ... а в TableValue_1/2 будет только id и value ...
Re: Дочерние таблицы. Оптимизация запросов.
Условия правильные написаны.caHek2x писал(а): ↑2017.05.09, 16:21 я вам указал что у вас в обоих связях одно и тоже условие ...
вы или принцип не понимаете или не знаете чего вы хотите ...
у вас в одной таблице цвет .. .в другой размер .. .ок ...
сделайте в таблице Table_1 столбцы color_id и size_id ... а в TableValue_1/2 будет только id и value ...
Вопрос организации данных здесь вроде не поднимался. Это уже другая тема.
Re: Дочерние таблицы. Оптимизация запросов.
исходя из того что ТС предполагает что из за разности названий и моделей в связи должен формироваться разный sql я выразил мысль о его непонимании или принципа или неверной структуре ... а он уже пусть делает выводы ...
Re: Дочерние таблицы. Оптимизация запросов.
Это уже лучше. В этом случае, конечно, будет много пустых значений для тех строк, которые не имеют в поле color_id соответствующих значений и также наоборот для size_id. Но по мне так это меньшее из зол.
Re: Дочерние таблицы. Оптимизация запросов.
Ясно. Тогда, полагаю, при работе с большим количеством записей в AR нужно использовать "Пакетное получение данных (batch(), each())"?
Re: Дочерние таблицы. Оптимизация запросов.
я когда достаю слишком много данных то работаю через asArray, чтоб не создавались обьекты а просто голые данные ... но опять же все от ситуации зависит ...
Re: Дочерние таблицы. Оптимизация запросов.
Как вариант. Только каменты почитай еще если будут проблемы 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) {
}
}