Новый тип связи в AR
- Stamm
- Сообщения: 407
- Зарегистрирован: 2010.03.14, 18:59
- Откуда: Россия, Москва
- Контактная информация:
Новый тип связи в AR
Сейчас есть два метода связей в AR:
1) Запрос через join
2) Отдельные запросы для каждой модели
А возможно ли сделать ещё один вид связи? Возможно это уже реализовано в каком-нибудь экстеншене (прошу кинуть ссылку, если есть).
Суть его следующая: мы запрашиваем из первой таблицы простым запросом без join.
После получения данных выбираются из связаной таблицы через 1 запрос, вида table1_id IN (1, 2, 3) и потом присваиваются нужным элементам из первой модели.
В чём плюс данного введения:
1) мы избавляемся от join'а или кучи мелких запросов:
2) возможно прозрачно использовать nosql (mongodb, etc) с такими связями
1) Запрос через join
2) Отдельные запросы для каждой модели
А возможно ли сделать ещё один вид связи? Возможно это уже реализовано в каком-нибудь экстеншене (прошу кинуть ссылку, если есть).
Суть его следующая: мы запрашиваем из первой таблицы простым запросом без join.
После получения данных выбираются из связаной таблицы через 1 запрос, вида table1_id IN (1, 2, 3) и потом присваиваются нужным элементам из первой модели.
В чём плюс данного введения:
1) мы избавляемся от join'а или кучи мелких запросов:
2) возможно прозрачно использовать nosql (mongodb, etc) с такими связями
-
- Сообщения: 1428
- Зарегистрирован: 2009.08.20, 22:54
- Откуда: Молдова, Бельцы
- Контактная информация:
Re: Новый тип связи в AR
В текущей версии - нет. CRelation есть, но, его так просто не перекроишь.
Re: Новый тип связи в AR
Это не отдельный вид связи скорее всего, а просто одна из разновидностей имеющихся. Ведь выборка из промежуточной таблицы все равно будет одной из обычных - has_one, has_many, many-many или stat.Stamm писал(а):Сейчас есть два метода связей в AR:
1) Запрос через join
2) Отдельные запросы для каждой модели
А возможно ли сделать ещё один вид связи? Возможно это уже реализовано в каком-нибудь экстеншене (прошу кинуть ссылку, если есть).
Суть его следующая: мы запрашиваем из первой таблицы простым запросом без join.
После получения данных выбираются из связаной таблицы через 1 запрос, вида table1_id IN (1, 2, 3) и потом присваиваются нужным элементам из первой модели.
В чём плюс данного введения:
1) мы избавляемся от join'а или кучи мелких запросов:
2) возможно прозрачно использовать nosql (mongodb, etc) с такими связями
В принципе, даже сейчас можно ПОЧТИ реализовать эту задачу. Для полной реализации мне пришлось влезть во фреймворк (очень зыбкий хак...):
class CJoinElement
...
Код: Выделить всё
public function getTableNameWithAlias()
{
// Hack for use custom join
if(!empty($this->relation) && !empty($this->relation->joinType) && strpos($this->relation->joinType, $this->tableAlias) > -1)
return '';
При этом суррогатная связь выглядит примерно так:
Код: Выделить всё
'lastStatusLog' => array(
self::HAS_ONE,
'OrderLog',
'order_id',
'joinType' => '
LEFT OUTER JOIN (
SELECT * FROM (SELECT * FROM `orderlog` WHERE `object` = '.OrderLog::OBJECT_STATUS.' ORDER BY `id` DESC) `ol` GROUP BY `order_id`
) `lastStatusLog`', // <--- ВАЖНО , псевдоним промежуточной таблицы должен быть таким же, как и название связи (для нормальной работы хака)
'together' => true
)
[Редкие] Записки пещерного человека
Re: Новый тип связи в AR
Совершенно неправильный метод.
1. Использование join работает очень быстро, поэтому для приложений требующих скорости следует использовать его.
2. Запрос по одному позволяет во первых сэкономить память на не хранении лишних данных, во вторых, когда в join таблицах объем данных очень большой, позволяет ускорить работу, потому что подгрузка будет только необходимых данных.
Соответственно первый метод позволяет писать быстрые приложения, второй экономить память. То что вы предлагаете - нечто среднее которое будет работать так же медленно как метод 2 и жрать столько же памяти как метод 1. Если вы использовали метод 2 и вам потребовались данные, поверьте быстрее будет переспросить полностью данные по методу 1, чем вычислить набор необходимых записей, потом их получить, а потом разложить их тормознутым интерпретатором байткода. И очень важно что код будет на столько прост, что в нем просто негде будет приютиться ошибке. Интерпретатор байткода PHP по сравнению с SQL является тормознутым!!!
Предложенный вами метод имеет смысл только для оооооооооооочень медленных каналов связи между БД и App, когда просто проталкивание нового набора данных будет слишком медленный и как следствие стоит сэкономить время на загрузке оригинального набора данных. Тоже самое относится если канал между БД и App платный или приходится платить за каждый запрос к БД. Мне кажется что такие варианты скорее экзотика.
Что касается mongoDB, думаю не стоит пытаться водрузить AR заточенный на реляционные модели пытаться водрузить документориентированные БД.
С полгода назад у меня была похожая идея, но потом вникнув в фреймворк больше я пришел к выводу что идея глупая, но я готов предметно пообсуждать ее, может я зря ее отбросил.
1. Использование join работает очень быстро, поэтому для приложений требующих скорости следует использовать его.
2. Запрос по одному позволяет во первых сэкономить память на не хранении лишних данных, во вторых, когда в join таблицах объем данных очень большой, позволяет ускорить работу, потому что подгрузка будет только необходимых данных.
Соответственно первый метод позволяет писать быстрые приложения, второй экономить память. То что вы предлагаете - нечто среднее которое будет работать так же медленно как метод 2 и жрать столько же памяти как метод 1. Если вы использовали метод 2 и вам потребовались данные, поверьте быстрее будет переспросить полностью данные по методу 1, чем вычислить набор необходимых записей, потом их получить, а потом разложить их тормознутым интерпретатором байткода. И очень важно что код будет на столько прост, что в нем просто негде будет приютиться ошибке. Интерпретатор байткода PHP по сравнению с SQL является тормознутым!!!
Предложенный вами метод имеет смысл только для оооооооооооочень медленных каналов связи между БД и App, когда просто проталкивание нового набора данных будет слишком медленный и как следствие стоит сэкономить время на загрузке оригинального набора данных. Тоже самое относится если канал между БД и App платный или приходится платить за каждый запрос к БД. Мне кажется что такие варианты скорее экзотика.
Что касается mongoDB, думаю не стоит пытаться водрузить AR заточенный на реляционные модели пытаться водрузить документориентированные БД.
С полгода назад у меня была похожая идея, но потом вникнув в фреймворк больше я пришел к выводу что идея глупая, но я готов предметно пообсуждать ее, может я зря ее отбросил.
Re: Новый тип связи в AR
Понятное дело, что это нехороший вариант и надо думать, когда его применять.TM123 писал(а):Совершенно неправильный метод.
Для моих целей это пока идеальный вариант. Возможно придется в дальнейшем пересмотреть.
[Редкие] Записки пещерного человека
Re: Новый тип связи в AR
Возможно, я не понял вопроса, но Yii ActiveRecord именно так и делает (использует два запроса, один из которых "IN"), когда извлекаются связанные данные, а для основных установлен LIMIT: http://www.yiiframework.com/doc/guide/1 ... .arr#sec-8
Когда я выводил с помощью CGridView список каталогов вместе со списком подкаталогов, в логе можно было наблюдать два запроса: первый извлекал сами каталоги, а второй генерировал большой IN из id каталогов (связь HAS_MANY).По умолчанию Yii использует "жадную" загрузку, то есть генерирует один SQL запрос, кроме того случая, когда к главной модели применяется LIMIT. Если выставить опцию together в описании связи в true, то мы получим единственный SQL запрос даже если используется LIMIT. Если использовать false, то выборка из некоторых таблиц будет производиться отдельными запросами. К примеру, для того, чтобы использовать отдельные SQL запросы для выборки последних записей и комментариев к ним, связь comments модели Post следует описать следующим образом:
Re: Новый тип связи в AR
Если посмотреть на логи то есть только 2 типа загрузки
1. Жадная, т.е. со всеми join связями которые заданы для жадной загрузки
2. Грузится только главная таблица, а все остальные данные по связям поштучно по мере поступления запросов на них.
1. Жадная, т.е. со всеми join связями которые заданы для жадной загрузки
2. Грузится только главная таблица, а все остальные данные по связям поштучно по мере поступления запросов на них.
- Stamm
- Сообщения: 407
- Зарегистрирован: 2010.03.14, 18:59
- Откуда: Россия, Москва
- Контактная информация:
Re: Новый тип связи в AR
Я не предлагаю использовать повсеместно и только в MySQL, а только как одну из опций, которая некоторым была бы полезна, особенно в тренде роста популярности нереляционных баз. Я эту тему больше создал для обсуждения и возможно для включения в следующий релиз yii2. Я думаю, что noSQL в нём будет из коробки. Тогда можно было бы довольно легко и прозрачно использовать AR и переключить на использование noSql решения вместо реляционной и подставить эту опцию.
Re: Новый тип связи в AR
Мне кажется что для nonSQL баз надо делать свой механизм. Входящая точка может быть одна CModel, но подключаться должны свои специализированные классы, а не просто класс который умеет работать с соответствующим диалектом SQL для конкретной БД, как это сделано сейчас.
Я не большой знаток документ ориентированных баз, но из того немногого что знаю мне кажется что надо делать так.
Я не большой знаток документ ориентированных баз, но из того немногого что знаю мне кажется что надо делать так.
Re: Новый тип связи в AR
Можно подсмотреть тут http://www.yiiframework.com/extension/directmongosuite.