Сохранение графических данных (Java) - PullRequest
7 голосов
/ 07 октября 2009

У меня есть приложение, которое использует графические (древовидные) пользовательские структуры. Структуры не являются настоящими деревьями, но в значительной степени все связано друг с другом. Количество данных также велико (могут существовать миллионы узлов). Узлы дерева могут различаться по типу, чтобы сделать его более интересным (наследование). Я не хочу изменять структуры данных для размещения постоянного хранилища.

Я хочу сохранить эти данные без особой дополнительной работы. Я нашел несколько вариантов решения этой проблемы, но не смог найти ничего подходящего именно для моих нужд. Возможные варианты: сериализация, базы данных с ORM (Hibernate?), JCR (JackRabbit?), Что-нибудь еще?

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

У кого-нибудь есть опыт или идеи по хранению таких данных?

Ответы [ 6 ]

5 голосов
/ 07 октября 2009

Поскольку ваши данные используют структуру данных графа (в основном: узлы и ребра / отношения), база данных графа будет очень хорошим совпадением. Смотрите мой ответ на Базы данных следующего поколения для некоторых ссылок. Я являюсь частью Neo4j проекта базы данных графов с открытым исходным кодом, см. эту ветку для некоторого обсуждения этого. Большим преимуществом использования Neo4j в таком случае, как у вас, является то, что нет проблем с отслеживанием сохранения / активации объектов или глубины активации и тому подобного. Вам, вероятно, не нужно будет менять структуры данных в вашем приложении, но, конечно, потребуется дополнительный код. Руководство по проектированию дает один пример того, как ваш код может взаимодействовать с базой данных.

2 голосов
/ 07 октября 2009

У меня почти точная проблема и использовал спящий режим. В конце проекта мы столкнулись с множеством проблем, потому что представление в основном заставляло весь граф помещаться в память даже при использовании ленивых типов выборки. Эти инструменты были хороши на ранних этапах, потому что мы могли быстро получить уровень БД, который дал бы нам что-то (хаззилхил). Только когда мы собирались улучшить производительность, мы поняли, что нам нужно написать более интеллектуальный уровень персистентности.

Можно ли провести предварительную обработку ваших данных? Если проблема аналогична, то стоит попытаться преобразовать данные в промежуточную форму, которая ближе к вашему взгляду, чем исходный домен, и сохранить ее в БД. Вы всегда можете вернуться к исходному источнику, используя тип отложенной выборки.

В основном мы использовали 4-уровневую систему: Domain DB, гибрид ViewModel-DB (предварительно обработанный слой), ViewModel, View

Преимущество этого этапа предварительной обработки (особенно с пользовательским интерфейсом в реальном времени) заключается в том, что вы можете размещать данные в ViewModel и красиво их отображать. Так много производительности в приложениях реального времени незначительно, просто будьте отзывчивы и покажите им что-нибудь приятное, пока они ждут. В нашем случае мы могли бы отображать области трехмерных блоков данных, которые были разбиты на страницы, данные, которые были связаны с загрузкой данных, могли также отображать визуальный индикатор. Гибрид ViewModel-DB также может делать такие приятные вещи, как очереди LRU, которые соответствуют данным нашего домена. Но самое большое преимущество заключалось в том, чтобы удалить прямые ссылки. У узлов было что-то похожее на URL к их связанным данным. При рендеринге мы можем отрисовать ссылку или сделать так, чтобы была ссылка, на которую мы только что поделили страницу.

Стойкость на уровне БД для начала была JPA (Hibernate), но в итоге таблицы, сгенерированные для нашей структуры наследования, были ужасны и сложны в обслуживании. В конце мы хотели получить больший контроль над таблицами, чем позволял JPA (или, по крайней мере, легко позволял). Это было трудное решение, так как JPA действительно облегчил работу со многими уровнями БД. Так как JPA держал все в порядке и POJO, он не требовал возиться с нашими типами данных. Так что это было мило.

Я надеюсь, что есть что-то, что вы можете извлечь из этого извилистого ответа, и удачи:)

2 голосов
/ 07 октября 2009

Поскольку вы указываете, что существует большое количество данных, вам, вероятно, нужен механизм, с помощью которого вы можете легко вводить данные по мере необходимости. Сериализация, вероятно, не очень проста для обработки больших объемов данных. Чтобы разбить его на управляемые части, вам нужно либо использовать отдельные файлы на диске, либо хранить их в другом месте. JCR (JackRabbit) - это скорее система управления контентом. Они хорошо работают для объектов типа «документ». Похоже, отдельные куски дерева, которое вы хотите сохранить, могут быть маленькими, но вместе они могут быть большими. Это не идея CMS.

Другой вариант, который вы упомянули, ORM, вероятно, ваш лучший вариант здесь. JPA (Java Persistence API) отлично подходит для выполнения ORM в Java. Вы можете написать в спецификации JPA и использовать Hibernate, Eclipselink или любой другой вариант провайдера месяца. Они будут работать с любой базой данных, которую вы хотите. http://java.sun.com/javaee/5/docs/api/index.html?javax/persistence/package-summary.html

Другим преимуществом JPA является то, что вы можете использовать ленивый FetchType для загрузки древовидных зависимостей. Таким образом, ваше приложение должно загружать только текущий набор элементов, над которыми оно работает. Поскольку необходимы другие вещи, слой JPA может извлекать их из базы данных по мере необходимости.

1 голос
/ 07 октября 2009

рассмотрите возможность хранения ваших узлов в базе данных, подходящей схемой может быть:

t1(node_id,child_id)
t2(node_id,data1,data2,..,datan)

затем используйте JDBC для доступа / изменения данных. если вы используете правильные индексы, он будет работать довольно хорошо, масштабируясь до 100 миллионов записей. У меня есть ощущение, что нужно избегать сериализации общих объектов, если производительность действительно важна, потому что вы теряете некоторый контроль над характеристиками производительности кода с этими решениями.

если вам нужна лучшая производительность, вы можете использовать слой memcached .

1 голос
/ 07 октября 2009

ORM, например, с использованием JPA api (Hibernate, EclipseLink, ...), вероятно, позволит очень быстро реализовать постоянство. Необработанная производительность всей целостности дерева, как правило, бывает сложно достичь по сравнению с простым JDBC. Поэтому, если ваш единственный критерий эффективности - сохранение всего дерева за один раз, это, вероятно, не лучший вариант.
С другой стороны, если вам также нужно загрузить дерево, синхронизировать изменения дерева, то JPA предлагает эти встроенные функции с (после небольшого изменения) большей производительностью, чем многие ручные реализации.

Сериализация в Java имеет тенденцию быть довольно медленной и порождать множество данных. Сериализация также довольно хрупкая, когда вы меняете класс в своем приложении, и совершенно бесполезна, если вам нужно синхронизировать изменения в дереве.

В той же категории, что и сериализация, вы можете сериализовать в XML и сохранить его в некоторой базе данных XML (Oracle XDB). Однако они предназначены для большей гибкости хранения / запросов, чем для необработанной скорости.

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

0 голосов
/ 08 октября 2009

Я полагаю, что решение вашей проблемы заключается в использовании Терракота в качестве механизма постоянного хранения. Я призываю вас прочитать эту прекрасную статью об этом.

Он решает две ваши основные проблемы: производительность и прозрачность . Он легко масштабируется до больших графиков, сохраняя при этом высокую производительность, благодаря эффективному механизму синхронизации, который отправляет только экземпляры различий по сети. Он также сохраняет ваш график прозрачно, поскольку работает на уровне виртуальной машины, освобождая вас от проблемы несоответствия импеданса, с которой вы столкнетесь при использовании альтернатив, упомянутых в других ответах (ORM или OCM).

Чтобы было ясно, Терракота не постоянное решение для каждого случая. Лучше всего его использовать, когда вам нужны данные, доступные при перезагрузке компьютера, и вам это нужно быстро. Это не очень хорошее решение, когда вам нужно «заархивировать» эти данные, например, если у вас есть требования для доступа к этим данным еще долго после того, как запущенная система перестанет с ними работать. Подумайте о заказах, поступающих в интернет-магазин. Вы, вероятно, хотите хранить эти заказы в течение многих лет после того, как они были выполнены. В этих случаях вы можете взглянуть на гибридный подход, при котором выбранные данные, которые необходимо архивировать, могут быть извлечены из кластера Terracotta и сохранены с использованием традиционной СУБД.

Для более полного обзора плюсов и минусов обязательно прочитайте этот пост StackOverflow , который охватывает больше мелочей при выборе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...