Первый альфа релиз phpLightOrm

whirlwind

TDD infected, paranoid
>умеет ли оно подтягивать такие отношения сразу?

Я бы дополнил - при необходимости. ИМХО в ORM самое сложное не вытянуть что-либо связанное, а определить когда это нужно делать.
 

zerkms

TDD infected
Команда форума
ИМХО в ORM самое сложное не вытянуть что-либо связанное, а определить когда это нужно делать.
в том то и дело - что эта задача не совсем тривиальная ;)
 

korchasa

LIMB infected
Автор оригинала: whirlwind
>умеет ли оно подтягивать такие отношения сразу?
Я бы дополнил - при необходимости. ИМХО в ORM самое сложное не вытянуть что-либо связанное, а определить когда это нужно делать.
Ну тут две большие разницы - когда необходимо, и когда можно было бы ;)
Прописывать и анализировать тип загрузки связанных доменных объектов не сложно. Только, ИМХО, это лучше доверить программисту.
 

Wicked

Новичок
По такому принципу Doctrine вытягивает связанные объекты. Потом, при создании связанных объектов, приходиться разгребать дублирующиеся записи. При бОльшем объёме выборки, больше данных передаётся в скрипт, больше памяти, больше разгребать. Т.е. объём выборки продавцов напрямую зависит от объёма выборки заказов.

Я решил попробовать по другому. Связанные объекты вытягиваются отдельным запросом. В этом случае, количество запросов равняется количеству вытягиваемых сущностей. Т.е., чтобы вытянуть заказы и продавцов, будет выполнено два запроса, независимо от объёма выборки, причём объём выборки продавцов не будет напрямую зависеть от объёма выборки заказов.
Doctrine_Collection::LoadRelated(). Вы просто не умеете ее готовить.

-~{}~ 28.02.08 22:35:

При этом не увидел у Вас, как можно вытащить связанные объекты с помощью join'а. Как Вы и говорили, это может повлечь некоторую избыточность в резалтсете, но иногда этим можно пренебречь. Если я это просто упустил, то как в этом случае будет работать limit?

-~{}~ 28.02.08 22:42:

Также не нашел внятных упоминаний про many-to-many relations. Насколько я понял, одни делаются за счет 2 x one-to-many. Верно?

-~{}~ 28.02.08 22:49:

Также странно было обнаружить, что lazy loading полей - это свойство модели, а не запроса к модели. Есть ли способ загружать такие поля вместе со всеми остальными? Например, я бы хотел грузить посты вместе с контентом, когда мне нужно показывать посты целиком, но грузить посты без контента, когда мне нужно показывать только заголовки.

-~{}~ 28.02.08 22:56:

Пока что прихожу к выводу, что проект соответствует совсему названию (это скорее хорошо, чем плохо). Вполне неплохая по задумке, простая, довольно качественно написанная ORM.

Но лично я бы не стал переходить на нее с доктрины ради 30% (не совсем понятно как измеренной) производительности, принимая во внимание, что доктрина погибче будет, и, очень вероятно, сможет за счет этого отбить эти 30% обратно.
 

nail

Новичок
Автор оригинала: atv
Результаты benchmark'а я ещё не подготовил к публикации. Сейчас могу только сказать, что данная библиотека оказалась быстрее Doctrine где-то на 30%. Propel обогнал данную ORM по селектам где-то на 50%, по остальным операциям отстал тоже где-то на 30%.
А кеш запросов (не результатов, а запросов) смог включить в Doctrine? А если померять с HYDRATE_ARRAY или HYDRATE_NONE?

Doctrine умеет фетчить результат не в виде объектов, а в виде массивов - это на случай, если нам не надо будет изменять и сохранять, а просто показать результат. HYDRATE_ARRAY работает быстрее чем HYDRATE_RECORD (который по умолчанию).

В Doctrine есть свой язык запросов (DQL), похожий на SQL. Если в DQL задать джоины, то не будет lazy load, а сразу нужные объекты - то есть программист сам определяет, нужна ли lazy подгрузка.
 

atv

Новичок
Doctrine_Collection::LoadRelated(). Вы просто не умеете ее готовить.
Да, невнимательно изучал.

При этом не увидел у Вас, как можно вытащить связанные объекты с помощью join'а.
Никак, я уже написал, что решил отказаться от этого варианта.

Также не нашел внятных упоминаний про many-to-many relations.
Это потому, что их нет, упоминаний. Реализация many-to-many пока отложена до лучших времён. Так как "они делаются за счет 2 x one-to-many."

Есть ли способ загружать такие поля вместе со всеми остальными?
Нет, возможно появится в будущем. Это было не приоритетной задачей для меня.

Но лично я бы не стал переходить на нее с доктрины ради 30% (не совсем понятно как измеренной)
Терпение, немного терпения. В ближайшее время постараюсь подготовить результаты.

принимая во внимание, что доктрина погибче будет
Ой ли. У LightOrm гибкость не отстаёт, при том что не используется специальный язык запросов. Я как раз и добивался большой гибкости, без использования языка запросов, чтобы поднять производительность.

А а если померять с HYDRATE_ARRAY или HYDRATE_NONE?
ОРМ перестаёт быть ОРМ, если она уже не создаёт объектов, а просто возвращает результат запроса, это уже будет не ОРМ, а квэри билдер. А я сравнивал ОРМ.

Вообще, при работе над LightOrm, основной упор я делал на работу с памятью. Кто из вас заставлял работать Propel или Doctrine несколько часов? И не пытайтесь, вывалятся через полчаса из-за нехватки памяти.

Я, в последнее время, сталкиваюсь с задачами, в которых скриптам приходиться работать по несколько часов, и обрабатывать по миллиону строк БД. LightOrm с этим справляется. В ней объекты автоматически освобождаются из памяти после того как стали ненужными.

Конечно, для сайта, расход памяти не самый критичный показатель, до определённого момента - возросшего количества посетителей. Вот тогда загрузка памяти станет узким местом. Ведь память, обычно, используют для увеличения производительности, за счёт кеширования. А она будет бесполезно израсходована на зависшие в памяти объекты, и станет, в даном случае, ещё и тормозом, так как её сперва нужно будет выделять, а потом очищать, по завершении работы скрипта, а эти опреации ресурсоёмкие.

Опять же, как я написал в целях проекта, одна из целей - НА ПРАКТИКЕ оценить целесообразность некоторых идей этой ОРМ. Так как практика, обычно, всё расставляет по свои местам.


P.S. В соответствии с требованиями PHP лицензии, название проекта изменено на LightOrm.
 

nail

Новичок
То есть проблема освобождения памяти при циклических связях в PHP может быть решена с помощью LightOrm?
В Doctrine для этого надо вызывать метод free():
http://www.phpdoctrine.org/documentation/api/0_10/Doctrine_Record#method_free
Helps freeing the memory occupied by the entity.
Cuts all references the entity has to other entities and removes the entity from the instance pool

Все таки на практике чаще всего выводятся данные на страницу для чтения.
А если нужно обработать миллионы строк в БД - то пишется форкающийся скриптик. Как показывает практика, иногда в PHP мемори ликов не избежать, даже когда делается "все правильно".
 

Wicked

Новичок
В ней объекты автоматически освобождаются из памяти после того как стали ненужными.
Откуда LightOrm знает, когда они стали ненужными?

А она будет бесполезно израсходована на зависшие в памяти объекты, и станет, в даном случае, ещё и тормозом, так как её сперва нужно будет выделять, а потом очищать, по завершении работы скрипта, а эти опреации ресурсоёмкие.
Имхо довольно сомнительные доводы.

Ой ли. У LightOrm гибкость не отстаёт, при том что не используется специальный язык запросов. Я как раз и добивался большой гибкости, без использования языка запросов, чтобы поднять производительность.
1) А только что Вы говорили, что не поддерживаются выборки с помощью джоинов, lazy loading на уровне запросов, many2many, HYDRATE_ARRAY, и т.д. ... Это гибкость? И потом, где гарантия, что когда Ваш roadmap будет реализован, LightORM не станет медленнее доктрины? Запас то всего ничего.
2) Кто мешает при работе с доктриной использовать объектный квери-билдер вместо DQL ? "It reduces the amount of query parsing that needs to be done and is therefore faster."
 

atv

Новичок
То есть проблема освобождения памяти при циклических связях в PHP может быть решена с помощью LightOrm?
Откуда LightOrm знает, когда они стали ненужными?
В LightOrm есть механизм подсчёта количества ссылок на объект. (см. ItemReference). Пока на объект остаются ссылки в коде, он продолжает жить в кеше. Как только, последняя ссылка была удалена, запускается метод release() объекта, который убирает циклические ссылки и удаляет объект из кеша.

Плюс к этому, есть буферизация, т.е. когда делаеш итерацию по таблице, в которой 10000 записей, то не беспокоишься о памяти, так как выборки происходят порциями, в зависимости от размера буфера. Это то, что относиться к управлению памятью.

Все таки на практике чаще всего выводятся данные на страницу для чтения.
Я уже высказывался в других топиках на эту тему. Я считаю неоправданным расточительством использовать ОРМ для построения ХТМЛ таблиц, тем более, что она для этого не предназначена. Для ХТМЛ таблиц вполне достаточно, и даже более практично использовать связку из DataSet и Grid.

Если хочется воспользоваться такой фичей ОРМ как маппинг полей таблицы, нет проблем. В LightOrm маппинг полей таблицы находиться на уровне квери билдера, а его можно использовать отдельно от ОРМ в любом другом месте, в том числе и с DataSet.

А только что Вы говорили, что не поддерживаются выборки с помощью джоинов, lazy loading на уровне запросов, many2many, HYDRATE_ARRAY, и т.д. ... Это гибкость?
Нет, это относится к функциональности, а не гибкости.

Кто мешает при работе с доктриной использовать объектный квери-билдер вместо DQL ?
Вот и я говорю, зачем городить огород из лишней функциональности, которая снижает общую производительность, чтобы потом от неё отказываться при оптимизации.

Вообще, у доктрины интересный подход, в заголовки вынесено что она может и то, и это, а в конце документации советы - лучше этого не использовать, так как проблемы с производительностью. А если включить HYDRATE_ARRAY, то получите самый быстрый квери билдер.

Поэтому, ещё раз подчёркиваю, одна из целей проекта, найти оптимальное соотношение между функциональностью и производительностью, которое можно определить только на практике.

И потом, где гарантия, что когда Ваш roadmap будет реализован, LightORM не станет медленнее доктрины? Запас то всего ничего.
Да, вобщем то, всё уже реализовано, осталось только many-to-many и lazy properties подправить, это, по идее, снизит производительность, но не более чем на 2-3 процента.
 

atv

Новичок
Но, в принципе, выполнимая ;)
Ой ля ля. Мы скоро запутаемся в терминологии :), пора наводить порядки в терминах.

Насколько я понял, zerkms, говорил о задаче подгрузки отношений 1:1, а то что описано в приведенной статье, это обычные join и bulk load. Если не обычные, то я даю разрешение ;) в этом топике объяснить разницу.

Насколько я понимаю, есть два способа вытягивать связанные объекты:
1) одним запросом, получая при этом дублирование строк
2) несколькими запросами, по количеству связанных сущностей, используя оператор IN()

Предлагаю оттолкнуться от этого утверждения, и дополнить/подправить/опровергнуть его, и для каждого случая определиться с используемыми терминами и их аналогами.
 

zerkms

TDD infected
Команда форума
1) одним запросом, получая при этом дублирование строк
какое дублирование?

-~{}~ 29.02.08 21:12:

в качестве примера, хотелось бы привести, например:

основная сущность: приватное сообщение (message)
связанные с ней: отправитель (message.sender_id <-> user.id), получатель (message.recipient_id <-> user.id)
 

atv

Новичок
какое дублирование?
когда выбираешь связь один-ко-многим, то сущность, входящая в отношение как "один", продублируется по количеству сущности "многие". (doctrine)

отправитель (message.sender_id <-> user.id), получатель (message.recipient_id <-> user.id)
Ты это назвал отношением один-к-одному?
 

Wicked

Новичок
atv
ОРМ перестаёт быть ОРМ, если она уже не создаёт объектов, а просто возвращает результат запроса, это уже будет не ОРМ, а квэри билдер.
Абсолютно не согласен. Единственное отличие от FETCH_RECORD - это формат результата. Все остальное остается прежним:
1) Все еще очень активно используется модель при формировании запроса. К тому же, когда применяется DQL, "квери билдер" там вообще не при делах.
2) "Результат запроса" все еще оформляется в соответствии с моделью. Если выбираются связанные объекты, будет сформирован многомерный массив - http://www.phpdoctrine.org/documentation/manual/0_10?one-page#improving-performance:fetch-only-what-you-need
Наверное стоит упомянуть, что если пользователь доктрины пользуется ArrayAccess-доступом и сущности выбираются только для r/o целей, то переключение между FETCH_ARRAY и FETCH_RECORD можно вообще делать безболезненно.

Плюс к этому, есть буферизация, т.е. когда делаеш итерацию по таблице, в которой 10000 записей, то не беспокоишься о памяти, так как выборки происходят порциями, в зависимости от размера буфера.
Можно поподробнее? Это делается множественными запросами с limit'ом, или как?

Конечно, для сайта, расход памяти не самый критичный показатель, до определённого момента - возросшего количества посетителей. Вот тогда загрузка памяти станет узким местом.
По мне так пусть лучше будет бОльшая нагрузка именно на бэкенды, чем на сервера баз данных... просто исходя из масштабируемости оных. Ваша же ORM пока демонстрирует более тяжелую работу с бд в угоду более деликатному отношению с бэкендами. Имхо не очень правильные у Вас приоритеты.

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

Вообще, у доктрины интересный подход, в заголовки вынесено что она может и то, и это, а в конце документации советы - лучше этого не использовать, так как проблемы с производительностью. [cut]

Поэтому, ещё раз подчёркиваю, одна из целей проекта, найти оптимальное соотношение между функциональностью и производительностью, которое можно определить только на практике.
Хорошо, давайте с этим тоже разберемся. Доктрина позволяет пользоваться большим кол-вом вкусных фишек, которые "из коробки" дают среднюю производительность (хотя, при этом есть такие вещи, как limit-subquery-algorithm). Когда проект вступает в фазу оптимизации, то у разработчика есть все необходимые "ниточки", чтобы довольно легко оптимизировать ее использование. Где-то использовать loadRelated, а где-то, наоборот, переписать на джоины или подзапросы (надеюсь, Вы не станете утверждать, что джоины и подзапросы бесполезны для производительности). Где-то воткнуть FETCH_ARRAY, и т.д., до тех пор, пока разработчика не станет устраивать производительность.

Так что ИМХО цель Вашего проекта сводится к принуждению пользоваться [якобы] заведомо оптимальными, при этом, как правило, менее удобными средствами.

Так что я считаю, что именно доктриновский подход является более гибким.

zerkms
Ты меня пугаешь. Потенциально будет дублирование sender'ов и recipient'ов .-)
 

atv

Новичок
Опубликовал результаты тестирования производительности LightOrm vs Propel vs Doctrine benchmark, правда, пока только циферки, потом допишу чего нибудь, по результатам обсуждения.


Абсолютно не согласен. Единственное отличие от FETCH_RECORD - это формат результата.
Для меня это самое важное отличие. Кстати, а зачем режим FETCH_ARRAY? Думаю для того, чтобы строить HTML таблицы. Так на это у меня тоже есть определённое мнение, которое я изложил на странице проекта LightOrm.

Можно поподробнее? Это делается множественными запросами с limit'ом
Да.

Ваша же ORM пока демонстрирует более тяжелую работу с бд в угоду более деликатному отношению с бэкендами.
Совсем нет, моя ORM позволяет настраивать свою работу с памятью. Размер буфера можно изменять, настраивая его на оптимальное значение при оптимизации. Это прибавляет больше гибкости, по сравнению с Doctrine.

Доктрина позволяет пользоваться большим кол-вом вкусных фишек, которые "из коробки" дают среднюю производительность
Кстати по поводу производительности, смотрите тесты выше.

надеюсь, Вы не станете утверждать, что джоины и подзапросы бесполезны для производительности
Не надейтесь, не стану :)

Так что ИМХО цель Вашего проекта сводится к принуждению пользоваться [якобы] заведомо оптимальными, при этом, как правило, менее удобными средствами.
Боже упаси, никакого принуждения, кто хочет, может пользоваться Doctrine :) А вот про меньшее удобство говорить рано, пока вы ей не воспользовались.

Так что я считаю, что именно доктриновский подход является более гибким.
Гибкость доктрины опирается на DQL, которое позволяет получать практически всё многообразие выборок языка SQL.

Я считаю, что мне удалось достичь такой же гибкости без использования DQL, благодаря API библиотеки. Конечно, возможно, я ещё не всё учёл, практика покажет.
 
Сверху