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

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

Вы точно видели на Хабре десятки статей, в которых описывают разницу между SQL и NoSQL. И хотя я поставил перед собой цель не повторяться, всё-таки описать основные моменты я должен. Постараюсь сделать это покороче и затем приложу пару ссылок на хорошие и более подробные статьи.

Если вы здесь не за этим, то ниже найдете классные графики эффективности SQL и NoSQL на разных мобильных платформах, а в конце — четкие советы, как между ними выбирать. А блок с теорией можно пропустить.

SQL (Structured Query Language) — это язык запросов, которые мы используем для работы с реляционными базами данных. У таких БД жесткая структура в виде таблиц. Вся информация там хранится в столбцах и строках. Так что структурированность — одно из главных преимуществ SQL баз данных.

Еще SQL — это надежно, поскольку у него большое сообщество и длинная история. Какие бы проблемы ни возникали с SQL в прошлом, сейчас они решены. А если даже что-то и пойдет не так — точно есть у кого спросить. Поэтому разработчику остается только писать кастомные ивенты: селекторы, джойны и т. д.

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

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

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

Плюсы

Минусы

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

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

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

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

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

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

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

Плюсы

Минусы

Базы данных 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.

Если у вас появились вопросы — жду вас в комментариях. А если хотите следить за новостями мобильной разработки и Flutter в частности — подписывайтесь на телегу нашего тимлида Саши Ворожищева.

Что еще почитать

Комментарии (14)


  1. Cobalt
    28.05.2024 15:46
    +4

    Как надо не любить читателей чтобы советовать им Isar ? Достаточно посмотреть что она уже больше года не обновляется, а обещанная 4 версия и того дольше "в разработке" находится. Вещь совершенно не юзабельная. Да хотяб просто вспомнить что Isar - это поменявший название и много вызвавший негатива в прошлом Hive! В нем остались все те же проблемы и добавилось еще куча новых. Чтобы потом не пришлось переезжать - используйте Sqlite или ОРМ для него Drift. Вообще не используйте NoSQL решения в проектах чуть сложнее калькулятора - потом будет больно переписывать!


    1. GameOwner
      28.05.2024 15:46

      Для ряда проектов SQL просто не позволит физически реализовать функционал-в силу чудовищной стоимости либо невозможности на текущем железе поднять инфру. Какой-нибудь средненький HFT фонд, катающий скромные 100М уе объема в сутки, желающий держать на своих серверах хотя бы сотню торгуемых инструментов-легко запишет весь требуемый датафид, используя EventSource/CQRS/NoSQL, с требуемой скоростью доступа к материализованному представлению по этим данным, правильно заточенному-будь то OrderBook либо подготовленные данные под ML, SQL на любой платформе и на любом железе для такого скромного набора датафидов скажет-"наши полномочия всё" :) А ведь есть те конторы, что хранят тысячи датафидов десятков бирж :) Кто-то правда еще дальше пошел и использует kdb+, но у него свои нюансы, начиная от стоимости, заканчивая пиковым перформансом, при прямых руках собственные реактивные велосипеды выходят шустрее.


      1. Cobalt
        28.05.2024 15:46

        Разговор именно про встраиваемую БД. На серверах можно использовать что угодно. Там у NoSQL решений нет таких проблем с безопасностью, производительностью и масштабируемостью как на мобилках.


      1. Kahelman
        28.05.2024 15:46

        1000 датафидов спокойно отображается в 1000 SQLite файлов. Так что SQL вам дозволит проводить обработку. В этом случае все-равно будет многопоточность приложение и большинство данных будут просто держаться в памяти. База нужна в редких случаях чтобы исторические данные подтянуть. А там где реальный HFT ( когда считают наносекунды потерянные на передачу данных по оптическому каналу) все равно будут использовать что-то своё и узко специализированное


    1. Atreides07
      28.05.2024 15:46

      Я вот с Isar переехал на sqlite с Drift и столкнулся с неожиданной багой. На проде и только на проде Drift периодически выбрасывает DriftRemoteException (Code 5) хотя подключение к БД открываю только один за время жизни приложения. Специально локально писал нагрузочные тесты с асинхронными запросами что бы воспроизвести проблему локально, но так и не получилось воспроизвести проблему. Я в итоге шаманствами с подключениям жизненного цикла пофиксил проблему, но осознанного и уверенного решения проблемы так и не получил. Поэтому и с Drift надо идти на прод осторожно.


  1. GameOwner
    28.05.2024 15:46
    +2

    Для хайлоада с 1М+ запросов на модификацию NoSQL гораздо предпочтительнее.

    Для 10М+ только NoSQL и остается.

    Хотя очевидно, что подобные требования нужны 0.0001% проектам :)


  1. Kahelman
    28.05.2024 15:46
    +8

    Похоже чат-ГПТ голлюцинирует….

    Если вы делаете маленькое приложение на узкую аудиторию или если вы делаете MVP для проверки гипотезы, то можно смело выбирать NoSQL-решение. Такие базы быстрые, с ними проще работать, они легко масштабируются. А если проект растет как на дрожжах — NoSQL можно быстро переписать на SQL

    Удачи вам NoSQL в SQL переделывать….

    Похоже автор вообще в руках баз данных не держал. Сравнивать абстрактный nosql с абстрактным sql на техническом ресурсе это уже за гранью добра и зла

    если свести всю статью к одной фразе:

    Не знаете как делать- берите SQLite.

    Будет шанс смигрироватт на PostgreSQL без большой головной боли. Или раскидаете данные по разным SQLite базам - скорее всего вы не Google и не FB и SQLite покроет потребности всех ваших 10-100 клиентов


    1. Neikist
      28.05.2024 15:46

      Чет я довольно сильно сомневаюсь что постгрю можно в принципе на мобилке развернуть. И что это вообще кому нибудь нужно.

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


  1. Fell-x27
    28.05.2024 15:46
    +1

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

    Если нужно работать с цельными сущностями и тебе нужно просто "тупое хранилище", используй для этой цели noSQL, ведь просто SQL будет оверкиллом. Если нужно работать с декомпозированными данными - используй SQL, ведь...ды просто а что тебе еще использовать? :)

    Это, блин, штуки, для разных задач. У них из общего - только 3 символа в названии подхода к работе. Но так-то и дрель с молотком это "строительные/монтажные инструменты" , да?


  1. leon-mbs
    28.05.2024 15:46
    +1

    Хайп вокруг nosql давно прошел когда стало очевидно что "серебряной пули" из них не получилось и nosql базы заняли отвдеенную им нишу быстрой обработки больших объемов key-value данных


  1. sergey-gornostaev
    28.05.2024 15:46

    Если вы делаете маленькое приложение на узкую аудиторию или если вы делаете MVP для проверки гипотезы, то можно смело выбирать NoSQL-решение. Такие базы быстрые, с ними проще работать, они легко масштабируются. 

    И часто у вас в маленьких приложениях на узкую аудиторию не хватает производительности СУРБД или возникает потребность в горизонтальном масштабировании?

    Если вы делаете энтерпрайз-решение

    То у вас, вероятно, будет множество разнотипных баз данных.


  1. Hivemaster
    28.05.2024 15:46

    Базы данных NoSQL быстрые и легкие.

    Давно например MongoDB лёгкой-то стала?


  1. Kanut
    28.05.2024 15:46
    +2

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

    И сразу вспомнилось:

    Четырнадцатый том сочинений Боконона озаглавлен так: «Может ли разумный человек, учитывая опыт прошедших веков, питать хоть малейшую надежду на светлое будущее человечества?» Прочесть Четырнадцатый том недолго. Он состоит всего из одного слова и точки: «Нет.»
    «Колыбель для кошки»


  1. MANAB
    28.05.2024 15:46

    Исходя из статьи, такое ощущение, что бд хранится у каждого пользователя приложения своя, сервер с API не нужен или вообще без БД. Почему у меня такое ощущение? Потому что ни слова про запросы API и сервер и потому, что автор писал, что если пользователь заероет приложение, то данные в noSQL не сохранятся или сохранятся битые.

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