Агрегатные функции в JDO GAE отсутствуют, что делать, как их заменить?

15 views
Skip to first unread message

Keus

unread,
Jul 1, 2010, 3:07:13 AM7/1/10
to Google App Engine for Java on Russian
В обычном SQL есть различные функции сложения, нахождения средней,
группировки и т.п., но GAE для своего JDO этого не поддерживает, но
мне необходимо сложить значения некоторых полей в моих объектах и не
помешало бы их ещё и сгруппировать. В общем, как я думаю, через запрос
этого не сделать, но как тогда подобные операции делаются?

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

Дмитрий Балаков

unread,
Jul 1, 2010, 4:47:15 AM7/1/10
to google-appengi...@googlegroups.com
Некорректно сравнивать JDO и SQL запросы - я бы сравнивал с такими фреймворками, как nhibernate :)
По существу же - тут в запросе получаете список объектов, а не произвольный набор полей, как в сиквеле - поэтому думаю, что подобной функциональности нет и быть не может. На самом деле я бы складывал на стороне сервера, если гнать на клиента этот список не надо - не все ли равно нагрузка упадет на хранилище или на сервер - тут эти два понятия несколько размываются.
Для облегчения жизни сервера же возможно есть смысл использовать MemCashe.

1 июля 2010 г. 11:07 пользователь Keus <dmiha...@gmail.com> написал:



--
с уважением, Балаков Дмитрий

Daniel Burdakov

unread,
Jul 1, 2010, 5:28:26 AM7/1/10
to google-appengi...@googlegroups.com
Насколько я понял, для аггрегатных функций предполагается не вычислять их каждый раз при запросе, а хранить их значение отдельно, и изменять его при добавлении/удалении/модификации данных. С точки зрения производительности это оправдано тем, что запросов на чтение обычно намного больше, чем запросов на модификацию. Однако в таком случае негативным фактором будет избыточность данных, и не в смысле занимаемого места, а в смысле возможности рассогласования счётчика и реальных данных (особенно если обновлять счётчик без транзакции)

1 июля 2010 г. 11:47 пользователь Дмитрий Балаков <bala...@gmail.com> написал:

Keus

unread,
Jul 1, 2010, 7:19:59 AM7/1/10
to Google App Engine for Java on Russian
Значит, я правильно понял, что группировки, суммирование и прочее надо
делать самому, так как штатных возможностей для этого нет и каждый
придумывает своё. Вообще мне это надо для получения определенных
отчетов из сохраненных данных.

Пока я вижу три варианта:

1. Изначально который я предположил, это <<тупо>> суммировать и
группировать значения в цикле. Если будет не много объектов, то в
принципе это вариант, но когда их будет много, то может возникнуть
проблема.

2. Создать специальные объекты в которых будут хранится все
необходимые суммы и группировки. Обновлять эти данные вместе с
добавлением, удалением или модификацией объектов. Я понимаю это как
создание независимого отношения <<один-ко-многим>>, где множество
основных объектов будут содержать ключ группирующего объекта (там
хранятся суммы и прочие сгруппированные данные). Но при независимом
отношении транзакции не работают, а значит, могут возникнуть проблемы
с <<синхронизацией>> данных. На что обратил внимание Даниил.

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

Дмитрий Балаков

unread,
Jul 1, 2010, 7:37:04 AM7/1/10
to google-appengi...@googlegroups.com
2-ой вариант мне нравиться больше - единственное, что его проектировать надо аккуратно - исходя не из самого списка отчетов, а данных которые интересно группировать/получать и прочее.

1 июля 2010 г. 15:19 пользователь Keus <dmiha...@gmail.com> написал:

Daniel Burdakov

unread,
Jul 1, 2010, 8:10:27 AM7/1/10
to google-appengi...@googlegroups.com
Второй вариант имеет сразу два подводных камня
1) С точки зрения datastore. Если данных много, то в одну entity group их запихнуть не получится, а значит локальные транзакции невозможны. Можно работать вообще без транзакций, но сбитые агрегаты - это фэйл. Другой вариант - это распределённые транзакции, судя по описанию они помогут во многих проблемах такого рода, однако я пока не пробовал работать с ними, только читал. Материалы по DT: http://code.google.com/intl/ru-RU/events/io/2009/sessions/DesignDistributedTransactionLayerAppEngine.html , http://danielwilkerson.com/dist-trans-gae.html , http://code.google.com/p/tapioca-orm/

2) С точки зрения программирования. Если агрегатов много, то на мой взгляд ужасно при каждом удалении/добавлении/изменении/пакетном удалении везде их обновлять. Логика агрегата оказывается размазана по куче методов, можно где-то забыть... Также при добавлении нового агрегата придётся:
  а) вычислить его текущее значение (понадобится делать только первый раз, значит придётся писать код который будет запущен только один раз)
  б) найти все места, где модифицируются объекты, от которых он зависит, и добавить туда код для его обновления
Возможно есть какие-то ORM, которые упрощают эти действия, буду рад узнать.

На мой взгляд идеально было бы, чтоб можно было заявить: "Это поле должно содержать результат запроса <<select sum(x) from ... >>", и дальше ORM или datastore сами вычисляют значение этого поля в первый раз, и обновляют его значение при всех модификациях объектов, от которых это поле зависит. Технически это вроде не сложно, похоже на построение и обновление индексов, а с этим GAE уже справляется.

Keus

unread,
Jul 1, 2010, 12:36:12 PM7/1/10
to Google App Engine for Java on Russian
Второй вариант, конечно, был бы лучше всего, но эти транзакции всё
портят.

Что-то я в документации я не могу найти описание распределенных
транзакций. Этот механизм ещё не реализован в GAE или для него ничего
особенного делать не надо, всё тоже самое, что и для локальных
транзакций?

Может быть, придется объединять 2 и 3 способы. Т.е. делается всё как
во втором, но периодически запускается проверка на правильность
ссумированных данных.

Такое ощущение, что GAE не рассчитан для сложных манипуляций с данными
и поэтому всё придется делать руками, со всеми последствиями.


On 1 июл, 19:10, Daniel Burdakov <kre...@kreved.org> wrote:
> Второй вариант имеет сразу два подводных камня
> 1) С точки зрения datastore. Если данных много, то в одну entity group их
> запихнуть не получится, а значит локальные транзакции невозможны. Можно
> работать вообще без транзакций, но сбитые агрегаты - это фэйл. Другой
> вариант - это распределённые транзакции, судя по описанию они помогут во
> многих проблемах такого рода, однако я пока не пробовал работать с ними,

> только читал. Материалы по DT:http://code.google.com/intl/ru-RU/events/io/2009/sessions/DesignDistr...,http://danielwilkerson.com/dist-trans-gae.html,http://code.google.com/p/tapioca-orm/

Daniel Burdakov

unread,
Jul 1, 2010, 1:07:11 PM7/1/10
to google-appengi...@googlegroups.com
В datastore распределенные транзакции не реализованы, они реализуются с помощью библиотеки на стороне клиента (под клиентом подразумеваю не браузер пользователя, а Ваш код на сервере). Всё взаимодействие с datastore идёт через эту библиотеку. И если во время распределённой транзакции поток был убит по таймауту - то при следующем обращении к datastore (возможно уже другим потоком), незавершённые транзакции будут откачены назад или завершены. Таким образом поддержка DT со стороны datastore не требуется.

Другое дело, что год назад на презентации про эту идею рассказали, черновик стандарта сделали, библиотеку (tapioca-orm) написали... Но с тех пор ни новостей ни обновлений нет, так что похоже это дело забросили, а жаль.

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

1 июля 2010 г. 19:36 пользователь Keus <dmiha...@gmail.com> написал:

Keus

unread,
Jul 2, 2010, 10:56:37 AM7/2/10
to Google App Engine for Java on Russian
На самом деле со вторым вариантом тупик. Пока не введут распределенную
транзакцию, оперативно агрегатные данные получить не получится.
Получается, что если нужно оперативно, то надо каждый раз прогонять
все исходные данные и вычислять то, что требуется. В общем как мне
кажется GAE не для таких вещей, по крайней мере, пока не будет
распределенных транзакций.

Единственный вариант это третий, т.е. периодическая <<агрегация>>
данных, т.е. смерится, что оперативности не будет. Но я посмотрел на
то, что мне надо получить и выходит несколько не простая задача. В
общем, задача не из легких, столько надо учесть, столько условий
разных. И всё это только потому, что нет агрегатных функций. :)


On 2 июл, 00:07, Daniel Burdakov <kre...@kreved.org> wrote:
> В datastore распределенные транзакции не реализованы, они реализуются с
> помощью библиотеки на стороне клиента (под клиентом подразумеваю не браузер
> пользователя, а Ваш код на сервере). Всё взаимодействие с datastore идёт
> через эту библиотеку. И если во время распределённой транзакции поток был
> убит по таймауту - то при следующем обращении к datastore (возможно уже
> другим потоком), незавершённые транзакции будут откачены назад или
> завершены. Таким образом поддержка DT со стороны datastore не требуется.
>
> Другое дело, что год назад на презентации про эту идею рассказали, черновик
> стандарта сделали, библиотеку (tapioca-orm) написали... Но с тех пор ни
> новостей ни обновлений нет, так что похоже это дело забросили, а жаль.
>
> Насчёт комбинации второго и третьего способов - это приемлемо, если мы
> показываем агрегированные данные пользователю. А если же результат агрегации
> используется в дальнейшем для принятия каких-либо решений, или дальнейших
> расчётов - то, даже если в дальнейшем (при следующей проверке) показатели
> будут пересчитаны, - будет уже поздно.
>

> 1 июля 2010 г. 19:36 пользователь Keus <dmihail...@gmail.com> написал:


>
>
>
> > Второй вариант, конечно, был бы лучше всего, но эти транзакции всё
> > портят.
>
> > Что-то я в документации я не могу найти описание распределенных
> > транзакций. Этот механизм ещё не реализован в GAE или для него ничего
> > особенного делать не надо, всё тоже самое, что и для локальных
> > транзакций?
>
> > Может быть, придется объединять 2 и 3 способы. Т.е. делается всё как
> > во втором, но периодически запускается проверка на правильность
> > ссумированных данных.
>
> > Такое ощущение, что GAE не рассчитан для сложных манипуляций с данными
> > и поэтому всё придется делать руками, со всеми последствиями.
>
> > On 1 июл, 19:10, Daniel Burdakov <kre...@kreved.org> wrote:
> > > Второй вариант имеет сразу два подводных камня
> > > 1) С точки зрения datastore. Если данных много, то в одну entity group их
> > > запихнуть не получится, а значит локальные транзакции невозможны. Можно
> > > работать вообще без транзакций, но сбитые агрегаты - это фэйл. Другой
> > > вариант - это распределённые транзакции, судя по описанию они помогут во
> > > многих проблемах такого рода, однако я пока не пробовал работать с ними,
> > > только читал. Материалы по DT:
> >http://code.google.com/intl/ru-RU/events/io/2009/sessions/DesignDistr...,

> >http://danielwilkerson.com/dist-trans-gae.html,http://code.google.com...

Reply all
Reply to author
Forward
0 new messages