Статьи

SQL против NoSQL: как выбрать

В предыдущей статье мы обсудили основные различия между базами данных SQL и NoSQL. В этом продолжении мы применим наши знания к конкретным сценариям и определим лучший вариант.

Подведем итог:

Базы данных SQL:

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

Базы данных NoSQL:

  • хранить связанные данные в JSON-подобных документах с именами и значениями
  • может хранить данные без указания схемы
  • обычно должен быть денормализован, чтобы информация об элементе содержалась в одном документе
  • не должно требовать СОЕДИНЕНИЯ (при условии использования денормализованных документов)
  • разрешить сохранение любых данных в любое время без проверки
  • гарантировать обновления одного документа, но не нескольких документов
  • обеспечить отличную производительность и масштабируемость
  • использовать объекты данных JSON для запросов
  • новые, захватывающие технологии.

Базы данных SQL идеально подходят для проектов, в которых могут быть определены требования и необходима надежная целостность данных. Базы данных NoSQL идеально подходят для несвязанных, неопределенных или развивающихся требований к данным, где скорость и масштабируемость важнее. Проще говоря:

  • SQL цифровой. Это работает лучше всего для четко определенных, дискретных предметов с точными спецификациями. Типичными примерами использования являются интернет-магазины и банковские системы.
  • NoSQL является аналогом. Это работает лучше всего для органических данных с требованиями жидкости. Типичными примерами использования являются социальные сети, системы управления клиентами и системы веб-аналитики.

Немногие проекты будут в точности соответствовать. Любой вариант может быть жизнеспособным, если у вас есть более мелкие или естественно денормализованные данные. Но, пожалуйста, учтите эти упрощенные примеры сценариев с широкими обобщениями! Вы знаете больше о своем проекте, чем я, и я бы не рекомендовал переходить с SQL на NoSQL или наоборот, если он не дает значительных преимуществ. Это твой выбор. Подумайте о плюсах и минусах в начале вашего проекта, и вы не ошибетесь.

Сценарий первый: список контактов

Давайте заново изобретем колесо и реализуем систему адресной книги на основе SQL. Наша начальная наивная таблица contact определяется следующими полями:

  • Я бы
  • заглавие
  • Имя
  • фамилия
  • Пол
  • телефон
  • Эл. адрес
  • адрес 1
  • Адрес 2
  • address3
  • город
  • область
  • почтовый индекс
  • страна

Проблема первая: мало кто имеет один телефонный номер. Вероятно, нам нужно по крайней мере три на стационарные, мобильные и рабочие места, но не имеет значения, сколько мы выделим — кто-то где-то захочет большего. Давайте создадим отдельный telephone стол, чтобы у контактов могло быть сколько угодно. Это также нормализует наши данные — нам не нужен NULL для контактов без номера:

  • contact_id
  • имя (текст, например, стационарный, рабочий, мобильный и т. д.)
  • число

Проблема вторая: у нас та же проблема с адресами электронной почты, поэтому давайте создадим похожую таблицу email :

  • contact_id
  • имя (текст, например домашний адрес, рабочий адрес и т. д.)
  • адрес

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

  • contact_id
  • имя (текст, например, дом, офис и т. д.)
  • адрес 1
  • Адрес 2
  • address3
  • город
  • область
  • почтовый индекс
  • страна

Наша оригинальная таблица contact была уменьшена до:

  • Я бы
  • заглавие
  • Имя
  • фамилия
  • Пол

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

Схема жесткая
Мы не учли имя, отчество контакта, дату рождения, компанию или должность. Неважно, сколько полей мы добавим, мы скоро получим запросы на обновление заметок, юбилеев, статусов отношений, учетных записей в социальных сетях, внутренних измерений, любимого типа сыра и т. Д. Предусмотреть каждый вариант невозможно, поэтому мы » d возможно создать таблицу других данных с парами имя-значение, чтобы справиться.

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

Наконец, полнотекстовый поиск затруднен. Если кто-то вводит строку «SitePoint» , мы должны проверить все четыре таблицы, чтобы определить, является ли это частью имени контакта, телефона, адреса электронной почты или адреса, и соответствующим образом оценить результат. Если вы когда-либо пользовались поиском в WordPress, вы поймете, насколько это может быть неприятно.

Альтернатива NoSQL

Наши контактные данные касаются людей. Они непредсказуемы и имеют разные требования в разное время. Список контактов выиграл бы от использования базы данных NoSQL, которая хранит все данные о человеке в одном документе в коллекции contacts :

 { name: [ "Billy", "Bob", "Jones" ], company: "Fake Goods Corp", jobtitle: "Vice President of Data Management", telephone: { home: "0123456789", mobile: "9876543210", work: "2244668800" }, email: { personal: "[email protected]", work: "[email protected]" }, address: { home: { line1: "10 Non-Existent Street", city: "Nowhere", country: "Australia" } }, birthdate: ISODate("1980-01-01T00:00:00.000Z"), twitter: '@bobsfakeaccount', note: "Don't trust this guy", weight: "200lb", photo: "52e86ad749e0b817d25c8892.jpg" } 

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

Поскольку данные контакта содержатся в одном документе, мы можем получить некоторую или всю информацию, используя один запрос. Полнотекстовый поиск также проще; в MongoDB мы можем определить индекс для всех contact текстовых полей, используя:

 db.contact.createIndex({ "$**": "text" }); 

затем выполните полнотекстовый поиск, используя:

 db.contact.find({ $text: { $search: "something" } }); 

Сценарий второй: социальная сеть

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

К тому же:

  • Большинство обновлений данных имеют единственную точку происхождения: пользователя. Маловероятно, что нам понадобится обновлять две или более записи одновременно, поэтому функциональность, подобная транзакциям, не требуется.
  • Несмотря на то, что думают некоторые пользователи, неудачное обновление статуса вряд ли вызовет глобальный крах или финансовые потери. Интерфейс и производительность приложения имеют более высокий приоритет, чем надежная целостность данных.

NoSQL, кажется, подходит. База данных позволяет нам быстро реализовать функции хранения различных типов данных. Например, все обновления статуса от пользователя могут быть помещены в один документ в коллекции status :

 { user_id: ObjectID("65f82bda42e7b8c76f5c1969"), update: [ { date: ISODate("2015-09-18T10:02:47.620Z"), text: "feeling more positive today" }, { date: ISODate("2015-09-17T13:14:20.789Z"), text: "spending far too much time here" } { date: ISODate("2015-09-17T12:33:02.132Z"), text: "considering my life choices" } ] } 

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

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

Сценарий третий: система управления складом

Рассмотрим систему, которая контролирует складские товары. Нам нужно записать:

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

Наши требования к данным:

  1. Общая информация о продукте, такая как количество в упаковке, размеры и цвет, может быть сохранена, но это дискретные данные, которые мы можем идентифицировать и применять ко всему. Мы вряд ли будем беспокоиться о таких особенностях, как скорость процессора ноутбука или предполагаемое время автономной работы смартфона.
  2. Необходимо минимизировать ошибки. У нас не может быть продуктов, исчезающих или перемещаемых в место, где уже хранятся различные продукты.
  3. В простейшем виде мы записываем перемещение предметов из одной физической области в другую — или удаляем из местоположения A и помещаем в местоположение B. Это два обновления для одного и того же действия.

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

Раскрой себя!

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

Лучший совет: подвергайте себя как можно большему количеству технологий. Эти знания позволят вам сделать обоснованное и беспристрастное суждение относительно SQL или NoSQL. Удачи.