Я реализую следующую модель для хранения пользовательских данных в моей таблице - у меня есть 2 столбца - uid
(первичный ключ) и meta
столбец, в котором хранятся другие данные о пользователе в формате JSON.
uid | meta
--------------------------------------------------
1 | {name:['foo'],
| emailid:['foo@bar.com','bar@foo.com']}
--------------------------------------------------
2 | {name:['sann'],
| emailid:['sann@bar.com','sann@foo.com']}
--------------------------------------------------
Это лучший способ (производительность мудрый, дизайн-накрест) , чем модель одной колонки-в-собственности, где таблица будет иметь много столбцов , как uid
, name
, emailid
.
Что мне нравится в первой модели, так это то, что вы можете добавить как можно больше полей без ограничений.
Кроме того, мне было интересно, теперь, когда я реализовал первую модель. Как мне выполнить запрос, например, я хочу выбрать всех пользователей, у которых есть имя, например, 'foo'?
Вопрос - Какой лучший способ хранения пользовательских данных (учитывая, что количество полей не фиксировано) в базе данных с использованием - JSON или столбец на поле? Кроме того, если реализована первая модель, как запросить базу данных, как описано выше? Должен ли я использовать обе модели, храня все данные, которые могут быть найдены по запросу в отдельной строке, а другие данные в JSON (это другая строка)?
Обновить
Так как столбцов, по которым мне нужно выполнять поиск, будет не слишком много, разумно ли использовать обе модели? Ключ для столбца для данных, которые мне нужно искать, и JSON для других (в той же базе данных MySQL)?
источник
Ответы:
Обновлено 4 июня 2017
Учитывая, что этот вопрос / ответ приобрел некоторую популярность, я решил, что это стоит обновить.
Когда этот вопрос был первоначально опубликован, MySQL не поддерживал типы данных JSON, а поддержка PostgreSQL находилась в зачаточном состоянии. Начиная с 5.7, MySQL теперь поддерживает тип данных JSON (в двоичном формате хранения), а PostgreSQL JSONB значительно вырос. Оба продукта предоставляют производительные типы JSON, которые могут хранить произвольные документы, включая поддержку индексации определенных ключей объекта JSON.
Тем не менее, я по-прежнему придерживаюсь своего первоначального утверждения, что ваши предпочтения по умолчанию при использовании реляционной базы данных должны по-прежнему быть столбцом на значение. Реляционные базы данных по-прежнему строятся при условии, что данные в них будут довольно хорошо нормализованы. Планировщик запросов имеет лучшую информацию по оптимизации при просмотре столбцов, чем при просмотре ключей в документе JSON. Внешние ключи могут создаваться между столбцами (но не между ключами в документах JSON). Важно: если большая часть вашей схемы достаточно изменчива, чтобы оправдать использование JSON, вы можете хотя бы подумать, является ли реляционная база данных правильным выбором.
Тем не менее, немногие приложения являются полностью реляционными или ориентированными на документы. Большинство приложений имеют некоторое сочетание обоих. Вот несколько примеров, где я лично нашел JSON полезным в реляционной базе данных:
При хранении адресов электронной почты и телефонных номеров для контакта, где хранить их как значения в массиве JSON гораздо проще, чем управлять несколькими отдельными таблицами
Сохранение произвольных пользовательских настроек ключ / значение (где значение может быть логическим, текстовым или числовым, и вы не хотите иметь отдельные столбцы для разных типов данных)
Хранение данных конфигурации, которые не имеют определенной схемы (если вы создаете Zapier или IFTTT и вам необходимо хранить данные конфигурации для каждой интеграции)
Я уверен, что есть и другие, но это лишь несколько быстрых примеров.
Оригинальный ответ
Если вы действительно хотите иметь возможность добавлять столько полей, сколько хотите, без ограничений (кроме произвольного ограничения размера документа), рассмотрите решение NoSQL, такое как MongoDB.
Для реляционных баз данных: используйте один столбец на значение. Помещение большого двоичного объекта JSON в столбец делает запрос практически невозможным (и мучительно медленным, когда вы действительно находите запрос, который работает).
Реляционные базы данных используют преимущества типов данных при индексации и предназначены для реализации с нормализованной структурой.
Как примечание: это не значит, что вы никогда не должны хранить JSON в реляционной базе данных. Если вы добавляете истинные метаданные или если ваш JSON описывает информацию, которую не нужно запрашивать и которая используется только для отображения, может оказаться излишним создать отдельный столбец для всех точек данных.
источник
virtually impossible to query
» - сегодня PSQL позволяет искать и индексировать его jsonb"For relational databases"
в вашем ответе = PКак и большинство вещей "это зависит". Это не правильно или неправильно / хорошо или плохо само по себе хранить данные в столбцах или JSON. Это зависит от того, что вам нужно делать с этим позже. Каков ваш прогнозируемый способ доступа к этим данным? Вам нужно будет ссылаться на другие данные?
Другие люди довольно хорошо ответили, что такое технический компромисс.
Не многие люди обсуждали, что ваше приложение и функции развиваются со временем и как это решение для хранения данных влияет на вашу команду.
Поскольку одно из соблазнов использования JSON состоит в том, чтобы избежать миграции схемы, и поэтому, если команда не дисциплинирована, очень легко вставить еще одну пару ключ / значение в поле JSON. Там нет миграции для этого, никто не помнит, для чего он. Там нет проверки на это.
Моя команда использовала JSON наряду с традиционными колонками в postgres, и сначала это была лучшая вещь с нарезанного хлеба. JSON был привлекательным и мощным, пока однажды мы не поняли, что гибкость обходится дорого, и это внезапно становится настоящей проблемой. Иногда эта точка очень быстро набирает обороты, и ее становится трудно изменить, потому что мы создали много других вещей на основе этого решения.
С течением времени добавление новых функций и данных в JSON приводило к более сложным запросам, чем то, что могло бы быть добавлено, если бы мы придерживались традиционных столбцов. Итак, мы начали вылавливать определенные ключевые значения обратно в столбцы, чтобы мы могли объединяться и сравнивать значения. Плохая идея. Теперь у нас было дублирование. Новый разработчик придет на борт и будет сбит с толку? Какое значение я должен сохранить обратно? JSON один или столбец?
Поля JSON стали мусорными ящиками для маленьких частей того и этого. Нет проверки данных на уровне базы данных, нет согласованности или целостности между документами. Это возлагало всю ответственность на приложение, вместо того чтобы получать жесткую проверку типов и ограничений из традиционных столбцов.
Оглядываясь назад, JSON позволил нам очень быстро выполнить итерацию и получить что-то за дверью. Это было здорово. Однако после того, как мы достигли определенного размера команды, ее гибкость также позволила нам повесить длинную веревку технического долга, что затем замедлило последующий прогресс в развитии функций. Используйте с осторожностью.
Задумайтесь над тем, какова природа ваших данных. Это основа вашего приложения. Как данные будут использоваться с течением времени. И как это может измениться?
источник
Просто выбросил его туда, но в WordPress есть структура для такого рода вещей (по крайней мере, WordPress был первым местом, где я наблюдал это, вероятно, он возник в другом месте).
Он позволяет использовать безграничные ключи и выполнять поиск быстрее, чем использование большого двоичного объекта JSON, но не так быстро, как некоторые решения NoSQL.
РЕДАКТИРОВАТЬ
Для хранения истории / нескольких ключей
и запрос через что-то вроде этого:
источник
emailid
ключ в примере, который я привел в своем вопросе.Недостаток подхода - именно то, что вы упомянули:
это делает поиск объектов ОЧЕНЬ медленным, так как каждый раз, когда вам нужно выполнить текстовый поиск по нему.
вместо этого значение на столбец соответствует всей строке.
Ваш подход (данные на основе JSON) подходит для данных, по которым вам не нужно искать, а нужно просто отображать их вместе с обычными данными.
Изменить: просто чтобы уточнить, вышеизложенное относится к классическим реляционным базам данных. NoSQL использует JSON для внутреннего использования и, вероятно, является лучшим вариантом, если это желаемое поведение.
источник
По сути, первая используемая модель называется хранилищем документов. Вы должны взглянуть на популярные базы данных NoSQL на основе документов, такие как MongoDB и CouchDB . По сути, в базе данных на основе документов вы храните данные в файлах json, а затем можете запрашивать эти файлы json.
Вторая модель - это популярная структура реляционных баз данных.
Если вы хотите использовать реляционную базу данных, такую как MySql, я бы предложил вам использовать только вторую модель. Нет смысла использовать MySql и хранить данные, как в первой модели .
Чтобы ответить на ваш второй вопрос, нет способа запросить имя, например «foo», если вы используете первую модель .
источник
Кажется, вы в основном сомневаетесь, использовать ли реляционную модель или нет.
В своем нынешнем виде ваш пример вполне соответствовал бы реляционной модели, но проблема может возникнуть, конечно, когда вам нужно будет развить эту модель.
Если у вас есть только один (или несколько предварительно определенных) уровней атрибутов для вашего основного объекта (пользователя), вы все равно можете использовать модель значения атрибута объекта (EAV) в реляционной базе данных. (Это также имеет свои плюсы и минусы.)
Если вы ожидаете, что вы получите менее структурированные значения, которые вы хотите искать в своем приложении, MySQL может оказаться не лучшим выбором.
Если бы вы использовали PostgreSQL, вы могли бы получить лучшее из обоих миров. (Это действительно зависит от фактической структуры данных здесь ... MySQL также не обязательно является неправильным выбором, и параметры NoSQL могут представлять интерес, я просто предлагаю альтернативы.)
Действительно, PostgreSQL может создавать индексы для (неизменяемых) функций (чего MySQL не может, насколько я знаю), и в последних версиях вы могли использовать PLV8 для данных JSON напрямую, чтобы создавать индексы для определенных интересующих элементов JSON, что улучшило бы скорость ваших запросов при поиске этих данных.
РЕДАКТИРОВАТЬ:
Смешивание двух моделей не обязательно является неправильным (при условии, что дополнительное пространство незначительно), но это может вызвать проблемы, если вы не убедитесь, что два набора данных синхронизированы: ваше приложение никогда не должно менять одну, не обновляя также другую. ,
Хороший способ для достижения этой цели - запуск автоматического запуска триггера путем запуска хранимой процедуры на сервере базы данных при каждом обновлении или вставке. Насколько я знаю, языку хранимых процедур MySQL, вероятно, не хватает поддержки для какой-либо обработки JSON. И снова PostgreSQL с поддержкой PLV8 (и, возможно, другие СУБД с более гибкими языками хранимых процедур) должны быть более полезными (автоматическое обновление реляционного столбца с использованием триггера очень похоже на обновление индекса аналогичным образом).
источник
через некоторое время присоединения на столе будут накладными расходами. скажем для OLAP. Если у меня есть две таблицы, одна таблица ORDERS, а другая ORDER_DETAILS. Чтобы получить все детали заказа, нам нужно объединить две таблицы, это сделает запрос медленнее, когда ни одна из строк в таблицах не увеличится, скажем, в миллионах или около того ... левое / правое соединение слишком медленнее, чем внутреннее соединение. Я думаю, что если мы добавим строку / объект JSON в соответствующую запись ORDERS, JOIN будет исключен. добавить генерацию отчетов будет быстрее ...
источник
короткий ответ, который вы должны смешать между собой, используйте json для данных, которые вы не собираетесь устанавливать с ними, например, контактные данные, адрес, данные о товарах
источник
Вы пытаетесь встроить нереляционную модель в реляционную базу данных, я думаю, что вам лучше использовать базу данных NoSQL, такую как MongoDB . Не существует предопределенной схемы, которая бы соответствовала вашему требованию не ограничивать количество полей (см. Типичный пример коллекции MongoDB). Ознакомьтесь с документацией MongoDB, чтобы получить представление о том, как вы будете запрашивать ваши документы, например,
источник
Как отмечали другие, запросы будут медленнее. Я бы предложил добавить хотя бы столбец «_ID» для запроса по этому вопросу.
источник