«Динамические» таблицы в SQL? - PullRequest
1 голос
/ 28 мая 2009

В настоящее время я работаю над некоторыми идеями для сайта - где я хочу, чтобы мои пользователи могли создавать «Таблицы», в которых хранятся данные, а затем разрешать им запрашивать эти данные (менее вызывающим образом). чем писать SQL-запросы и, надеюсь, проще, чем использовать Excel).

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

CREATE TABLE 'Tables' (
   Id INT NOT NULL PRIMARY KEY,
   NAME VARCHAR(255)
)

CREATE TABLE 'TableColumns' (
   Id INT NOT NULL PRIMARY KEY,
   TableId INT NOT NULL FOREIGN KEY ON 'Tables',
   NAME VARCHAR(255)
)

CREATE TABLE 'TableRows' (
   Id INT NOT NULL PRIMARY KEY,
   TableId INT NOT NULL FOREIGN KEY ON 'Tables',
   RowNumber INT NOT NULL
)

CREATE TABLE 'TableValues' (
   RowId INT NOT NULL PRIMARY KEY,
   ColumnId INT NOT NULL PRIMARY KEY,
   Value VARCHAR(255)
)

(обратите внимание, что в таблице TableValues ​​есть 2 поля первичного ключа, она должна представлять собой «составной» первичный ключ, не слишком беспокоитесь о том, что мой синтаксис не является допустимым SQL, просто нужно показать идея).

Я провел небольшое тестирование с этим и смог успешно выполнить простые запросы (простая фильтрация, упорядочение и т. Д.). Мой способ сделать это состоял в том, чтобы сначала запросить таблицу TableRows - для фильтрации я затем отфильтровал строки, столбцы которых не соответствовали критериям, и для сортировки я отсортировал RowIds на основе содержимого их столбца (как указано в указанной сортировке). Результатом стал список идентификаторов строк в нужном порядке, с этого момента он просто выбирал то, что нужно.

Все это прекрасно работает, но я немного застрял здесь. Мне бы хотелось как-то представить различные типы данных (что является моей главной проблемой), а также позже выяснить, как выполнять объединения.

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

Я знаю, что всегда мог просто создавать таблицы в моей базе данных с запросами, создаваемыми на лету в C #, и аналогичным образом выполнять запросы, используя только SQL-запросы - однако я никогда не был большим поклонником того, чтобы позволить пользователям "создавать" запросы по отношению к моей базе данных, как это - и мне кажется, что это приведет к тому, что появятся многие ошибки - и в худшем случае в итоге пользователь сможет так или иначе уничтожить базу данных.

Кроме того, моя проблема заключается в том, как я могу решить эту проблему таким образом, чтобы это имело смысл с точки зрения C #. До сих пор я думаю, что опираюсь на использование LINQ, а затем создаю свои собственные методы расширения, которые бы применяли необходимую функциональность - это ExtensionMethods, расширяющий IQueryable.

Так что мне бы очень хотелось, чтобы были некоторые идеи о том, как это можно сделать, идеи о том, как настроить производительность, идеи о том, как работать с отдельными типами данных в таблице (конечно, сохраните тип в столбце таблицы, но как на самом деле сохранить значение, чтобы я мог фильтровать, сортировать и т. д. по нему? - без добавления столбца «TextValue», «MoneyValue» и т. д. в таблицу tablevalues). И последнее, но не менее важное, мы надеемся, что некоторые хорошие обсуждения здесь - я, по крайней мере, считаю, что это несколько интересная тема.

Ответы [ 9 ]

9 голосов
/ 28 мая 2009

Почему-то каждый сталкивается с этой идеей в тот или иной момент.

Кажется, правильно, это должно работать.

Было бы. Вроде.

Комментарии о TheDailyWTF имеют смысл. Реорганизация СУБД поверх СУБД - действительно не очень хорошая идея. Мета-метафора даст вам

  • нижняя система
  • кошмар обслуживания

Если вам действительно нужна такая гибкость (не так ли?), Вы бы потратили гораздо больше времени на реализацию слоя, позволяющего хранить метаданные в некоторых таблицах и генерировать схему для реальных таблиц в базе данных. *

Есть несколько примеров систем такого типа, о которых я знаю:

  • Microsoft OSLO (в частности, система репозитория)
  • серверная архитектура ASAM-ODS (ищите пакет ASAM-ODS)

И я уверен, что есть и другие.

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

Я действительно чувствую, что единственный правильный ответ на тип системы, которую вы предлагаете: не .

6 голосов
/ 28 мая 2009

Это интересная идея, но использование SQL таким образом, вероятно, будет очень болезненным со временем.
Если я вас правильно понял, вы хотите, чтобы пользователи могли определять структуры данных, а затем сохранять данные в этих структурах. Вы также хотите иметь возможность запросить его. Я думаю, что, возможно, есть несколько других способов сделать это;

  • А как насчет использования XML? Разрешить каждому пользователю хранить XML-файл для каждой «таблицы» и просто поддерживать его схему. Каждая «строка» будет элементом XML с дочерними элементами. Вы можете при желании вставить XML в SQL или просто сохранить его другими способами. Это не очень хорошо работает с большими наборами данных, но для тысяч записей это удивительно быстро; Я провел несколько тестов с 20+ МБ XML-файлами в C # и смог их создать, прочитать и проанализировать менее чем за 1 секунду. Используя LINQ to XML, вы можете даже создавать довольно сложные запросы и объединения. Я бы не использовал XML для крупной корпоративной системы, но вы удивитесь, насколько далеко он зайдет на современных компьютерах с большим объемом памяти и быстрыми процессорами - и он бесконечно гибкий.
  • Не могли бы вы вместо этого использовать объектно-ориентированную базу данных (Матисс и т. Д.)? Я сам не имел опыта в этом, но я думаю, что вы можете довольно легко сделать что-то вроде подхода XML, но с лучшей производительностью.
  • Amazon Simple DB: если я правильно помню, это, по сути, база данных на основе пары имя / значение, которую вы можете использовать. Может ли ваше приложение использовать это в фоновом режиме вместо того, чтобы вам не приходилось иметь дело со всей сантехникой? Если вам приходилось платить за SQL Server, то Amazon DB может быть дешевле и может масштабироваться, но без таких вещей, как реляционные запросы.
3 голосов
/ 28 мая 2009

Дизайн, который вы показываете в своем первоначальном вопросе, представляет собой вариант дизайна Entity-Attribute-Value .

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

Но у EAV много недостатков. Вот только один: как бы вы сделали любой данный столбец обязательным (эквивалент ограничения NOT NULL)?

Реляционная база данных предполагает, что вы знаете таблицы заранее и можете их определять. СУБД не является подходящим инструментом для полностью динамических отношений или отношений с полностью переменными наборами атрибутов. Для этого есть ряд других технологий, таких как XML, RDF или CouchDB .

См. Также мой ответ на " Базы данных следующего поколения ." *

2 голосов
/ 28 мая 2009

С риском для множества отрицательных голосов, почему бы просто не установить MS Access?

1 голос
/ 28 мая 2009

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

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

Теперь я знаю, что это идет вразрез со всей практикой работы с базами данных, но я денормализовал данные для каждой «Таблицы» так, как они у вас есть, и физически создал таблицу в базе данных с именем Table_1, Table_2.

Я создал и удалил Table_1 и Table_2 на основе триггеров в таблице Tables, добавил и удалил столбцы в эти таблицы с помощью триггеров в таблице TableColumns, вставил и удалил строки с триггерами в таблице TableRows и обновил значения с помощью триггеров на таблица TableValues.

Да, как и ожидалось, наша производительность при записи значительно снизилась, но наша производительность при чтениях (что было чрезвычайно важно в то время) была значительно улучшена, поскольку мы могли читать непосредственно из этих «денормализованных» таблиц.

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

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

1 голос
/ 28 мая 2009

Я не уверен, почему все ненавидят, и никто на самом деле не пытается ответить на ваш вопрос. Даже если в конечном итоге это вопрос «как бы вы реализовали Документы Google», это все равно справедливый вопрос.

Предполагая, что вы продумали, действительно ли вы хотите это сделать (я полагаю, в этом вся ненависть), вот, по крайней мере, лучшая идея:

DATA_TABLE {
    TABLEID INT,
    INT1 INT,
    INT2 INT,
    VARCHAR1 VARCHAR(255),
    ... etc
}

Затем где-то хранятся метаданные, в которых записывается, как называется конкретный TABLEID, какие поля используются, и каковы их имена, обращенные к пользователю, и т. Д. Объединения легко поддерживать, поскольку они являются просто самостоятельными объединениями в таблице данных. Храните ли вы указанные метаданные в базе данных или где-либо еще, зависит от вас.

Этот подход может работать идеально (я могу засвидетельствовать, что многие успешные сайты .com использовали такую ​​схему, как с теми, с кем я был связан, так и с людьми, которые были), но для достижения оптимальной производительности я бы порекомендовал использовать CHAR поверх VARCHAR, выравнивание ваших кортежей, чтобы они хорошо помещались на страницах и т. Д.

Я думаю, это довольно (очень) похоже на ответ dsteele

1 голос
/ 28 мая 2009

Я столкнулся с подобным подходом в надстройке Microsoft Business Contact Manager для Outlook. Они обрабатывают типы полей так, чтобы иметь таблицу, определяющую тип для каждого поля, затем они сохраняют фактические значения полей в таблице, содержащей только столбцы Varbinary. Преобразование в / из varbinary контролируется таблицей типов полей.

0 голосов
/ 28 мая 2009

SharePoint делает это и многое другое поверх SQL Server. Я хотел бы исследовать, как SharePoint использует SQL Server.

0 голосов
/ 28 мая 2009

Вы определенно хотите упростить это - разрешите своим пользователям создавать таблицы, возможно, в TEMPDB. Простое добавление суффикса схемы к таблицам «CREATE TABLE» d может позволить вам избежать использования их в болтовнях РЕАЛЬНЫХ системных таблиц. Позволяет вам легко их фильтровать. Проблема в том, что большинство баз данных не позволяет не-dba создавать таблицы, поэтому требуется предварительная настройка. Вы можете даже создать схему в своей базе данных специально для этого и наложить ограничения на размер и размер таблицы, если ваша база данных поддерживает их.

Не изобретай велосипед.

Сделайте это таким образом, и вы автоматически получите объединения, союзы и т. Д. И интерфейсы с Crystal Reports и другими инструментами, которые не требуют настройки вашей конкретной схемы.

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