Предостережение Лектор
Поскольку Datomic является новым, и мой опыт работы с ним ограничен, этот ответ ни в коем случае не следует рассматривать как передовой опыт. Воспринимайте это как введение в Datomic для тех, у кого есть реляционный опыт и кто стремится к более продуктивному хранилищу данных.
Начиная
В Datomic вы моделируете данные своего домена как сущности, которые обладают значениями для атрибутов. Поскольку ссылка на другой сущность может быть значением атрибута, вы можете моделировать отношения между Сущности просто.
На первый взгляд, это не так уж сильно отличается от того, как данные моделируются в традиционной реляционной базе данных. В SQL строки таблицы — это сущности, а имена столбцов таблицы — атрибуты, которые имеют значения. Связь представлена внешним ключом Value в одной строке таблицы, ссылающимся на первичный ключ Value другой строки таблицы.
Это сходство приятно, потому что вы можете просто набросать свои традиционные диаграммы ER при моделировании вашей предметной области. Вы можете полагаться на отношения так же, как в базе данных SQL, но вам не нужно возиться с внешними ключами, так как это обрабатывается за вас. Записи в Datomic являются транзакционными, а ваши чтения согласованными. Таким образом, вы можете разделить свои данные на объекты с любой степенью детализации, которая кажется вам подходящей, полагаясь на соединения для получения более широкой картины. Это удобство, которое вы теряете во многих хранилищах NoSQL, где обычно используются БОЛЬШИЕ денормализованные сущности для достижения некоторого полезного уровня атомарности во время обновлений.
На данный момент, у вас хорошее начало. Но Datomic гораздо более гибок, чем база данных SQL.
Пользуясь
Время по своей сути является частью всех данных Datomic, поэтому нет необходимости специально включать историю ваших данных как часть вашей модели данных. Это, пожалуй, самый обсуждаемый аспект Datomic.
В Datomic ваша схема не определена жестко в «прямоугольной форме», необходимой для SQL. То есть сущность1 может иметь любые атрибуты, необходимые для удовлетворения вашей модели. Сущность не обязательно должна иметь NULL
или значения по умолчанию для неприменимых к ней атрибутов. И вы можете добавлять атрибуты к конкретному отдельному объекту по своему усмотрению.
Таким образом, вы можете изменять форму отдельных сущностей с течением времени, чтобы реагировать на изменения в вашем домене (или изменения в вашем понимании домена). Ну и что? Это мало чем отличается от хранилищ документов, таких как MongoDB и CouchDB.
Разница в том, что с Datomic вы можете атомарно применять изменения схемы ко всем затрагиваемым объектам. Это означает, что вы можете выполнить транзакцию для обновления формы всех сущностей, на основе произвольной логики предметной области, написанной на вашем языке[2], которая будет выполняться, не затрагивая читателей, пока преданный идее. Я не знаю ничего близкого к такой мощности ни в реляционном, ни в хранилище документов.
Ваши сущности также не определены жестко как "живущие в одной таблице". Вы решаете, что определяет «тип» сущности в Datomic. Вы можете быть явным и указать, что каждый объект в вашей модели будет иметь атрибут :table
, который означает, что это за «тип». Или ваши объекты могут соответствовать любому количеству «типов», просто удовлетворяя требования к атрибутам каждого типа.
Например, ваша модель может потребовать, чтобы:
- Человеку требуются атрибуты
:name
, :ssn
, :dob
- Сотруднику требуется
:name
, :title
, :salary
- Резидент требует
:name
, :address
- Участнику требуются
:id
, :plan
, :expiration
Что означает сущность, подобную мне:
{:name "Brian" :ssn 123-45-6789 :dob 1976-09-15
:address "400 South State St, Chicago, IL 60605"
:id 42 :plan "Basic" :expiration 2012-05-01}
можно предположить, что это Person
, Resident
и Member
но НЕ Employee
.
Запросы Datomic выражаются в журнале данных и могут включать правила, выраженные на вашем родном языке, со ссылками на данные и ресурсы. которые не хранятся в Datomic. Вы можете хранить Функции базы данных как первоклассные значения внутри Datomic. Они напоминают хранимые процедуры в SQL, но ими можно манипулировать как значениями внутри транзакции, а также они написаны на вашем языке. Обе эти функции позволяют вам выражать запросы и обновления более ориентированным на предметную область способом.
Наконец, несоответствие импеданса между объектно-ориентированным и реляционным мирами всегда расстраивало меня. Использование функционального языка, ориентированного на данные (Clojure), помогает в этом, но Datomic стремится обеспечить надежное хранилище данных, которое не требует умственной гимнастики для перехода от кода к хранилищу.
Например, объект, полученный из Datomic, выглядит и действует как карта Clojure (или Java). Его можно передать на более высокие уровни приложения без преобразования в экземпляр объекта или общую структуру данных. Обход отношений этой сущности будет лениво извлекать связанные сущности из Datomic. Но с гарантией того, что они будут соответствовать исходному запросу даже при одновременном обновлении. И эти объекты будут казаться простыми старыми картами, вложенными в первый объект.
Это делает моделирование данных более естественным и, на мой взгляд, гораздо менее сложным.
Возможные ловушки
Конфликтующие атрибуты
Приведенный выше пример иллюстрирует потенциальную ловушку в вашей модели. Что, если позже вы решите, что :id
также является атрибутом Employee
? Решение состоит в том, чтобы организовать ваши атрибуты в пространства имен. Таким образом, у вас будут и :member/id
, и :employee/id
. Если вы сделаете это заранее, это поможет избежать конфликтов в будущем.
Определение атрибута нельзя изменить (пока)
После того, как вы определили атрибут в своем Datomic как определенный тип, индексированный или нет, уникальный и т. д., вы не можете изменить это позже. Здесь мы говорим ALTER TABLE ALTER COLUMN
на языке SQL. А пока вы можете создать замещающий атрибут с правильным определением и переместить существующие данные.
Это может звучать ужасно, но это не так. Поскольку транзакции сериализуются, вы можете отправить ту, которая создает новый атрибут, копирует в него ваши данные, разрешает конфликты и удаляет старый атрибут. Он будет работать без помех со стороны других транзакций и может использовать логику предметной области на вашем родном языке для выполнения своих задач. По сути, это то, что РСУБД делает за кулисами, когда вы выдаете ALTER TABLE
, но вы называете правила.
Не будьте «ребенком в кондитерской»
Гибкая схема не означает отсутствие модели данных. Я бы посоветовал заблаговременно смоделировать вещи разумным образом, как и для любого другого хранилища данных. Используйте гибкость Datomic в будущем, когда вам нужно, а не только потому, что вы можете.
Избегайте хранения больших, постоянно меняющихся данных
Datomic не является хорошим хранилищем данных для больших двоичных объектов или очень больших данных, которые постоянно меняются. Потому что он сохраняет историческую запись предыдущих значений и нет способа очистить старые версии (пока). Такие вещи почти всегда лучше подходят для хранилища объектов, такого как S3. Обновление: есть способ отключить историю на для каждого атрибута. Обновление: теперь также есть способ акцизных данных; тем не менее, сохранение ссылок на внешние объекты, а не на сами объекты, по-прежнему может быть лучшим подходом к обработке больших двоичных объектов. Сравните эту стратегию с использованием байтовых массивов.
Ресурсы
Примечания
- Я имею в виду объект в смысле строки, а не в смысле таблицы, который более правильно описывается как тип объекта.
- Насколько я понимаю, в настоящее время поддерживаются Java и Clojure, но возможно, что в будущем будут поддерживаться и другие языки JVM.
person
bkirkbri
schedule
13.05.2012