SQL vs NoSQL: как выбрать архитектуру БД для мобильного приложения, чтобы потом не пришлось ничего переписывать

807
#Разработка 28 мая 2024
Привет! Меня зовут Никита Грибков, я Flutter-разработчик в AGIMA. В сети море статей о различиях между SQL и NoSQL, но в большинстве из них много теории и почти совсем нет прикладных советов. Я пошел другим путем: ниже постараюсь внятно объяснить, какую систему и в каком случае выбирать. Спойлер: всё зависит от проекта и амбиций заказчика. Конечно, сосредоточусь на мобильной разработке, но основные принципы подойдут и в вебе.

Базовая теория

Фотография

Вы точно видели на Хабре десятки статей, в которых описывают разницу между SQL и NoSQL. И хотя я поставил перед собой цель не повторяться, всё-таки описать основные моменты я должен. Постараюсь сделать это покороче и затем приложу пару ссылок на хорошие и более подробные статьи.
Если вы здесь не за этим, то ниже найдете классные графики эффективности SQL и NoSQL на разных мобильных платформах, а в конце — четкие советы, как между ними выбирать. А блок с теорией можно пропустить.
SQL (Structured Query Language) — это язык запросов, которые мы используем для работы с реляционными базами данных. У таких БД жесткая структура в виде таблиц. Вся информация там хранится в столбцах и строках. Так что структурированность — одно из главных преимуществ SQL баз данных.
Еще SQL — это надежно, поскольку у него большое сообщество и длинная история. Какие бы проблемы ни возникали с SQL в прошлом, сейчас они решены. А если даже что-то и пойдет не так — точно есть у кого спросить. Поэтому разработчику остается только писать кастомные ивенты: селекторы, джойны и т. д.


NoSQL — это нереляционные базы данных, у них нет жесткой структуры. И тут разобраться проще на примере. Предположим, у нас есть класс — пользователи. У каждого пользователя есть ID, имя, фамилия, год рождения и прочее. Все эти данные помещаются в отдельный файл (а не в таблицу) и впредь там и находятся. Всё взаимодействие происходит только с этим файлом. Ты уже не можешь забрать какое-то одно поле, например ID. Ты работаешь только с этим классом целиком.

Подробно об обоих подходах можно почитать у коллег.

Преимущества и недостатки SQL

Плюсы Минусы Заголовок 3 Заголовок 4 Заголовок 5 Заголовок 6 Заголовок 7 Заголовок 8 Заголовок 9
SQL подходит для более сложных задач. Если у тебя 10 тысяч чеков и тебе нужно посмотреть, сколько ты потратил за год на молоко, то важно иметь под рукой структурированную таблицу. В ней будет отдельное поле «Молоко», и SQL сможет собрать данные именно по ней. А чтобы работать с NoSQL в таком формате, придется выгрузить базу данных целиком, пробежаться по всему массиву наших чеков, выделить поле «Молоко» и только потом с ним работать. Это неудобно, поэтому тут явно лучше SQL.


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

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

Сложность. Написание кода в SQL требует хорошей сноровки. Во-первых, мы должны писать высоконагруженный код, который быстро обработает любые запросы. А во-вторых, мы должны делать его декомпозировано. Из этого следует, что мы пишем большое количество кода, которого не можем не писать — иначе у нас просто ничего не выйдет.


В некоторых базах данных, которые работают непосредственно с SQL, например SQLite, приходится писать целые селекторы и джойны. то есть прямые запросы в базу данных SQL. Это сложно, поскольку нужно соблюдать определенную структуру.


Сложная масштабируемость. Допустим, у нас две таблички — два каких-то класса, которые мы собираемся хранить. Чтобы хранить третий класс, придется начинать всё сначала: создать под него табличку и написать под него ивенты, которые будут срабатывать. В SQL нет какого-то общего пространства, в котором мы создаем объект и потом с ним работаем.

Нужен блок Нужен блок Нужен блок с табличкой для статей на вихре Нужен блок Нужен блок Нужен блок с табличкой для статей на вихре Нужен блок

Преимущества и недостатки NoSQL

Плюсы Минусы Заголовок 3 Заголовок 4 Заголовок 5 Заголовок 6 Заголовок 7 Заголовок 8 Заголовок 9
Базы данных NoSQL быстрые и легкие. Часто в них интегрированы генераторы кода, которые облегчают работу. Мы, грубо говоря, просто пишем аннотации, и благодаря им код частично генерируется. При этом мы, например, не пишем классы-обертки над теми классами, которые хотим хранить, а получаем их благодаря кодогенерации.


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

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


Ограниченная поддержка транзакций. Нужно приложить много усилий, чтобы сделать базу данных NoSQL такой же безопасный, как SQL. Об этом я уже упоминал выше. Например, во Flutter можно использовать отдельный изолят, то есть отдельный поток, для выполнения этих транзакций. На основном потоке, на котором запущено всё приложение, обрабатывается логика, рисуются UI-интерфейсы, рендерятся объекты и прочее. А на параллельном запросе происходят транзакции. Так мы гарантируем, что транзакция будет быстрая и надежная.

Нужен блок Нужен блок Нужен блок с табличкой для статей на вихре Нужен блок Нужен блок Нужен блок с табличкой для статей на вихре Нужен блок

Использование во Flutter, Kotlin и Swift

Для разных платформ подходят разные виды баз данных SQL:


  • Flutter: поддерживает SQLite — это библиотека, которая работает на базе SQL, но при этом доработана под мобильное приложение.
  • Kotlin: чаще всего используют Room — это что-то вроде интерфейса для работы с SQL базами данных.
  • Swift: обычно применяют CoreData — фреймворк для управления SQL.

Для NoSQL на всех трех платформах чаще всего можно увидеть использование общих решений. Это может быть облачная платформа Firebase или MongoDB. MongoDB в Kotlin и Swift представлена в виде библиотеки Realm, на Flutter либа с одноименный названием.
Но отдельно расскажу про Isar — крутую NoSQL базу данных для Flutter. Ее сделали ребята, которые раньше работали над библиотекой Hive. По сути, Isar — это улучшенная версия Hive, и она действительно сильно выигрывает у других нереляционных баз.
  1. Isar очень быстрая. Это отчасти снимает проблему с транзакционной безопасностью. Пользователь просто не успевает сделать что-то, что прервет транзакцию.
  2. У Isar есть статическая типизация.
  3. Isar, благодаря реактивности и внутренней архитектуре, хорошо масштабируется. Поэтому может сохранять асинхронные и синхронные запросы.
  4. В Isar много функций, и среди них — полнотекстовый поиск.

    Предположим, у вас есть класс юзера, у которого есть ID, имя, фамилия, год рождения. Таких юзеров в базе 10 тысяч. Чтобы работать с типичной базой NoSQL, нам нужно сделать запрос на выгрузку всех пользователей, пробежаться по всему массиву, и отфильтровать нужных людей. В Isar же не нужно проводить столько операций. Можно просто отфильтровать по определенному полю, примерно как в SQL. Поэтому мы можем одним запросом отсортировать базу данных, запросить только нужных пользователей и вернуть их.
  5. В Isar встроен полезный инструмент — линки. Они позволяют настроить отношение одного объекта к другому.

Перформанс приложения

Говорить об особенностях SQL и NoSQL в вакууме можно, но сложно. Поэтому я провел небольшой эксперимент, чтобы показать, как реально работают упомянутые библиотеки. На каждой платформе попробуем поработать с двумя базами данных: одна реляционная, другая — нет. Сравнивать будем на 50 тысячах запросов.
В этом случае нас интересуют четыре действия:

  • создание запроса;
  • чтение объектов;
  • обновление;
  • удаление.

Вот что у нас получается:
Фотография

Чем меньше миллисекунд уходит на обработку запроса, тем лучше. На графике видно, что Room создает запросы быстрее, чем Realm. Но разница настолько незначительная, что пользователь вообще вряд ли что-то заметит. Видим, что на Flutter намного быстрее Isar, а на Swift — реляционный CoreDate. Измерения проводились на одинаковых объемах и типах данных, график может немного измениться при других вводных.
Однако эти цифры помогают увидеть разницу между SQL и NoSQL. NoSQL зачастую быстрее и эффективнее.

Так как же выбрать между SQL и NoSQL?

Тут всё зависит от потребностей и задач бизнеса.
  • Если вы делаете маленькое приложение на узкую аудиторию или если вы делаете MVP для проверки гипотезы, то можно смело выбирать NoSQL-решение. Такие базы быстрые, с ними проще работать, они легко масштабируются. А если проект растет как на дрожжах — NoSQL можно быстро переписать на SQL.
  • Если вы делаете средний по объему проект, я бы рекомендовал SQL. Хотя, если очень хочется, то можно и NoSQL. Но тут есть некоторые особенности: выбирайте нереляционные базы, только если у вас есть налаженные ивенты, налаженная имплементация баз данных и опыт работы с NoSQL.
  • Если вы делаете энтерпрайз-решение, советую обращаться только к SQL. Представим, что в каком-то крупном маркетплейсе 10 тысяч пользователей оплатили покупки, но не получили товары, потому что транзакция данных прошла некорректно. Цена ошибки тут слишком высока — поэтому только SQL.

Контент-хаб

0 / 0
+7 495 981-01-85 + Стать клиентом
Услуги Кейсы Контент-хаб