Схема динамической базы данных - PullRequest
63 голосов
/ 16 сентября 2008

Какая рекомендуемая архитектура для предоставления хранилища для динамической логической схемы базы данных?

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

Несколько возможностей для иллюстрации:

  • Создание / изменение объектов базы данных с помощью динамически генерируемого DML
  • Создание таблиц с большим количеством разреженных физических столбцов и использование только тех, которые требуются для «наложенной» логической схемы
  • Создание «длинной, узкой» таблицы, в которой значения динамического столбца хранятся в виде строк, которые затем необходимо повернуть для создания «короткого, широкого» набора строк, содержащего все значения для конкретной сущности
  • Использование системы типов BigTable / SimpleDB PropertyBag

Будем весьма благодарны за любые ответы, основанные на опыте реального мира.

Ответы [ 16 ]

36 голосов
/ 16 сентября 2008

То, что вы предлагаете, не ново. Множество людей попробовали это ... большинство обнаружило, что они преследуют "бесконечную" гибкость и вместо этого получают намного, намного меньше, чем это. Это «плотина» дизайна базы данных - данные поступают, но получить их практически невозможно. Попробуйте придумать концепцию написания кода для ЛЮБОГО рода ограничений, и вы поймете, что я имею в виду.

Конечным результатом обычно является система, которая НАМНОГО сложнее отлаживать, поддерживать и полна проблем с согласованностью данных. Это не всегда случай, но чаще всего так и происходит. Главным образом потому, что программисты не видят приближение этого крушения поезда и не могут защититься от него. Кроме того, часто заканчивается случай, что «бесконечная» гибкость действительно не так уж необходима; это очень неприятный "запах", когда команда разработчиков получает спецификацию, которая говорит: "Черт возьми, я понятия не имею, какие данные они собираются здесь размещать, поэтому давайте добавим WHATEVER" ... и с конечными пользователями все в порядке наличие заранее определенных типов атрибутов, которые они могут использовать (закодируйте общий # телефон и позвольте им создать любой из них - это тривиально в хорошо нормализованной системе и поддерживает гибкость и целостность!)

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

Зачем начинать с шансов, наложенных на вас так сильно?

Не верите мне? Google "One True Lookup Table" или "Дизайн одной таблицы". Некоторые хорошие результаты: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:10678084117056

http://thedailywtf.com/Comments/Tom_Kyte_on_The_Ultimate_Extensibility.aspx?pg=3

http://www.dbazine.com/ofinterest/oi-articles/celko22

http://thedailywtf.com/Comments/The_Inner-Platform_Effect.aspx?pg=2

19 голосов
/ 16 сентября 2008

Сильно типизированное поле XML в MSSQL сработало для нас

15 голосов
/ 19 ноября 2009

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

Если вам нужно разрешить своим клиентам это делать, вот несколько советов:
- Создайте надежный инструмент администрирования для выполнения изменений схемы и не допускайте внесения этих изменений любым другим способом.
- сделать его административной функцией; не разрешать обычным пользователям доступ к нему.
- Журнал каждой детали о каждом изменении схемы. Это поможет вам отладить проблемы, а также даст вам данные CYA, если клиент делает что-то глупое.

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

9 голосов
/ 26 сентября 2010

У меня аналогичное требование и я решил использовать схему без MongoDB .

MongoDB (от "humongous") - это масштабируемая, высокопроизводительная и не ориентированная на документы база данных с открытым кодом, написанная на языке программирования C ++. (Википедия)

Основные характеристики:

  • имеет богатую функциональность запросов (возможно, ближайшую к SQL-базам данных)
  • производство готово (foursquare, sourceforge использовать его)

Lowdarks (вещи, которые вы должны понимать, чтобы вы могли правильно использовать монго):

  • нет транзакций (на самом деле транзакции есть, но только для атомарных операций)
  • этот материал здесь: http://ethangunderson.com/blog/two-reasons-to-not-use-mongodb/
  • долговечность .. в основном материал, связанный с кислотой
7 голосов
/ 16 сентября 2008

Я сделал это в реальном проекте:

База данных состояла из одной таблицы с одним полем, которое представляло собой массив из 50. На нем был установлен индекс «слова». Все данные были без типизации, поэтому «индекс слов» работал как ожидалось. Числовые поля были представлены в виде символов, а фактическая сортировка была выполнена на стороне клиента. (При необходимости все еще можно иметь несколько полей массива для каждого типа данных).

Логическая схема данных для логических таблиц содержалась в одной и той же базе данных с другой строкой таблицы 'type' (первый элемент массива). Он также поддерживает простое управление версиями в стиле копирования при записи с использованием того же поля типа.

Преимущества:

  1. Вы можете динамически переставлять и добавлять / удалять столбцы, не нужно выполнять дамп / перезагрузку базы данных. Любые новые данные столбца могут быть установлены в начальное значение (практически) в нулевое время.
  2. Фрагментация минимальна, поскольку все записи и таблицы имеют одинаковый размер, иногда это дает лучшую производительность.
  3. Все схемы таблиц являются виртуальными. Возможна любая структура логической схемы (даже рекурсивная или объектно-ориентированная).
  4. Это хорошо для данных «однократная запись, в основном для чтения, без удаления / пометка как удаленные» (большинство веб-приложений на самом деле такие).

Недостатки:

  1. Индексирование только полными словами, без сокращений,
  2. Возможны сложные запросы, но с небольшим снижением производительности.
  3. Зависит от того, поддерживает ли предпочитаемая вами система баз данных массивы и индексы слов (она была дополнена в СУРБД PROGRESS).
  4. Реляционная модель только в голове программиста (т.е. только во время выполнения).

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

6 голосов
/ 16 сентября 2008

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

Если вам нужно хранить разнородные данные, например, как в сценарии CMS, я бы предложил хранить XML, проверенный XSD, в строке. Конечно, вы теряете производительность и возможности легкого поиска, но имхо, это хороший компромисс.

С 2016 года забудьте про XML! Используйте JSON для хранения нереляционной сумки данных с соответствующим типом столбца в качестве внутреннего. Обычно вам не нужно запрашивать по значению внутри пакета , что будет медленным, даже если многие современные базы данных SQL понимают JSON изначально.

3 голосов
/ 16 сентября 2008

Создать 2 базы данных

  • DB1 содержит статические таблицы и представляет «реальное» состояние данных.
  • DB2 бесплатна для пользователей по своему усмотрению - им (или вам) придется писать код для заполнения своих таблиц странной формы из DB1.
3 голосов
/ 16 сентября 2008

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

Кроме того, Google недавно выпустила свой внутренний протокол обмена данными, буфер протокола, с открытым исходным кодом через свой кодовый сайт. Система баз данных, смоделированная по этому подходу, была бы весьма интересна.

Проверьте следующее:

Модель значения атрибута сущности

Буфер протокола Google

3 голосов
/ 16 сентября 2008

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

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

Чтобы уточнить, что я имею в виду под "мета-схемой":

CREATE TABLE data (
    id INTEGER NOT NULL AUTO_INCREMENT,
    key VARCHAR(255),
    data TEXT,

    PRIMARY KEY (id)
);

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

2 голосов
/ 05 марта 2014

Я знаю, что это старая тема, но я думаю, что она никогда не теряет актуальности. Я сейчас разрабатываю что-то подобное. Вот мой подход. Я использую настройки сервера с MySQL, Apache, PHP и Zend Framework 2 в качестве среды приложения, но она должна работать также с любыми другими настройками.

Вот простое руководство по реализации, вы можете развить его дальше от него.

Вам потребуется реализовать собственный интерпретатор языка запросов, поскольку эффективный SQL будет слишком сложным.

Пример:

select id, password from user where email_address = "xyz@xyz.com"

Физическая структура базы данных:

Таблица 'specs': (должна кэшироваться на вашем уровне доступа к данным)

  • id: int
  • parent_id: int
  • имя: варчар (255)

Таблица 'items':

  • id: int
  • parent_id: int
  • spec_id: int
  • данные: varchar (20000)

Содержимое таблицы specs:

  • 1, 0, «пользователь»
  • 2, 1, 'email_адрес'
  • 3, 1, «пароль»

Содержимое таблицы 'items':

  • 1, 0, 1, ''
  • 2, 1, 2,'xyz@xyz.com'
  • 3, 1, 3, «мой пароль»

Перевод примера на наш собственный язык запросов:

select id, password from user where email_address = "xyz@xyz.com"

для стандартного SQL будет выглядеть так:

select 
    parent_id, -- user id
    data -- password
from 
    items 
where 
    spec_id = 3 -- make sure this is a 'password' item
    and 
    parent_id in 
    ( -- get the 'user' item to which this 'password' item belongs
        select 
            id 
        from 
            items 
        where 
            spec_id = 1 -- make sure this is a 'user' item
            and 
            id in 
            ( -- fetch all item id's with the desired 'email_address' child item
                select 
                    parent_id -- id of the parent item of the 'email_address' item
                from 
                    items 
                where 
                    spec_id = 2 -- make sure this is a 'email_address' item
                    and
                    data = "xyz@xyz.com" -- with the desired data value
            )
    )

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

Плохой пример, не используйте это, избегайте этого, вместо этого кешируйте таблицу спецификаций!

select 
    parent_id, 
    data 
from 
    items 
where 
    spec_id = (select id from specs where name = "password") 
    and 
    parent_id in (
        select 
            id 
        from 
            items 
        where 
            spec_id = (select id from specs where name = "user") 
            and 
            id in (
                select 
                    parent_id 
                from 
                    items 
                where 
                    spec_id = (select id from specs where name = "email_address") 
                    and 
                    data = "xyz@xyz.com"
            )
    )

Я надеюсь, что вы поняли идею и можете сами определить, возможен ли для вас такой подход.

Наслаждайтесь! : -)

...