Зачем NoSQL программистам

топ 100 блогов rainman_rocks10.06.2010
В последнее время, как видим, пошла мода на NoSQL.
Термин, собака, размыт до черезвычайности, под ним все подразумевают разное, кто во что горазд - кто-то интересуется переработанными RDBMS типа BigTable, кто-то болеет за key-value storage, парни с PostgreSQL вообще пошутили на тему QUEL.

Сконцентрируемся всё-таки на основном значении: системы хранения данных вида key-document. Популярность оных вот хорошо обсуждают с организационной точки зрения (краткий пересказ: это всё пионерские игрушки, люди просто не умеют готовить кошек ленятся нанимать хороших DBA). Я же, будучи всего лишь низменным разработчиком, попробую разглядеть вопрос со стороны технической.

У меня на счёт причин этого феномена есть интересная теория.

Люди, как верно замечено, по зову души уходят от SQL. Сначала уходили на ORM, теперь бегут на NoSQL. Почему бегут? Причины, как обычно, чисто человеческие: потому что SQL им неудобен. Давайте смотреть где и в каком месте именно неудобен. Для этого достаточно посмотреть в сторону чего бегут.

А бегут они в сторону JSON. JSON есть классический персонаж сказки - Золушок, бедный бастард, порождение флуктуаций мятущегося разума Брэндана Эйка, который был подобран доброй феей-Крокфордом, отряхнут от пыли и выведен в народ. Не обладая ни массивной маркетинговой поддержкой XML, ни идеологическим минимализмом лисповых s-expressions, новичок стал феноменально популярен. Комбинация чисел и строк, упрятанных в произвольно вкладывающиеся списки (= массивы) и кортежи с именованными полями (= объекты, = ассоциативные массивы) оказалась на практике наиболее удобным и универсальным способом представления типичных структур данных.

JSON стал катализатором (если вообще не создателем) моды на NoSQL. Хранилища типа key-value существовали с незапамятных времён (BerkeleyDB был даже встроен в MySQL), но в мэйнстрим так и не пошли, и даже эксперименты с XML-базами ничем особым не запомнились, кроме нескольких статей на The Daily WTF. А тут вот нате: читабельный и естественный формат представления структур данных, мечта разработчика. Знай себе обращайся к именованным полям да работай со списками - ты это и так уже делаешь в любом языке программирования. Заметим, что популярные ORM пытаются свести SQL примерно к тем же операциям. Разработчик хочет работать в привычных ему абстракциях.

Чего же у нас из благ JSON'а нету в классической реляционной системе? Реляционная БД - набор таблиц. Каждая таблица суть список кортежей. Элементы кортежа - те же скалярные типы, что и в JSON: числа и строки. So far so good: таблица более универсальна чем список и кортеж, её можно выродить и в тот, и в другой. Все элементы вроде на месте, чего ж не хватает?

Беда первая
: кортеж в кортеж можно вложить только непрямым способом, через foreign key. Foreign key собой представляет, в общем-то, тот же указатель/ссылку, к которым программисты и так привыкли. Другое дело, что в обычных ЯП "разадресация" этого указателя происходит либо прозрачно, либо при помощи простого typecast'а. В SQL же приходится прибегать к несложной, но раздражающей магии, типа джойнов/подзапросов. Ну или тупо ещё один дополнительный запрос (что неприятно для производительности).

А вот беда вторая, более серьёзная: вложить список в кортеж ещё труднее. Для этого нужны обратные ссылки. Поясню на примере.

Делаем платформу для блогов. У нас есть три основные таблицы -  пользователи, посты и камменты. Ясное дело, что в нашей программе, отображающей страницы блога, посты  логичнее всего будут представлены следующим типом:
class Post {
    String title;
    String message;
    DateTime date;
    List<Comment> comments;
    // другие поля
}

Но в реляционной БД у нас всё будет иначе. Поле comments из таблицы Post пропадёт, а вместо него в таблице Comment появится поле post_id. А список комментов для конкретного поста будет находиться выборкой по данному полю.

Конечно же, по этому полю будет сделан индекс. Разумеется, выборки будут производиться достаточтно быстро. Но! неприятный психологический факт остаётся неприятным психологическим фактом: совершенно обычные, привычные каждому программисту списки в реляционных БД искажены до неузнаваемости и хранятся в неявном виде, где-то в индексах.

(Заметим, что способы впихнуть списки в кортеж всё-таки есть: например, поле-массив в PostgreSQL или строковой суррогат в MySQL, которым, подозреваю, многие веб-девелоперы малодушно грешат. Но использование их неудобно, связано с ограничениями и вообще не "feels right")

Это раздражает. При переходе из кода в SQL программисту приходится выворачивать мозг наизнанку. Он не чувствует привычного контроля над структурами данных.  Знакомые алгоритмы искажаются. Более того, ему не совсем понятно, для чего это нужно.

Зато смотрящему с DB-башни наблюдателю всё, конечно, понятно. Реляционная система хранения оптимизирована для запросов (буква Q в SQL недаром стоит в центре). Перевод списков в индексы превращает порядоченную структуру данных, привычную программисту, в некоторое аморфное облако, из которого при помощи запросов волшебно извлекаются разнообразные представления. Приверженцам классических RDBMS вообще непонятно как в NoSQL можно делать выборки.

Выборки, тем не менее, в NoSQL делать можно. Просто те же самые индексы вы создадите руками. В нашем примере с блогом, если вам понадобится упорядочивать камменты не только по дате, но и по, например, рейтингам (как это делают на stackoverflow), вы просто добавите в каждый пост ещё один список:
class Post {
    String title;
    String message;
    DateTime date;
    List<Comment> comments;
    List<Comment> commentsByRatings;
}

Дублирования данных не будет - это же просто список указателей, по объёму равный тем же индексам.

Короче, вопрос вполне решаем. Просто вся эта возня с индексами (включая их обновление при изменении данных и поддержку консистентности) теперь ложится на плечи программиста. И программист готов платить такую цену. Потому что он, сука, хочет САМ КОВЫРЯТЬСЯ В СВОИХ ПРИВЫЧНЫХ СТРУКТУРАХ ДАННЫХ. А не доверять сложной магии планировщика запросов и его непонятно где спрятанным индексам.

Повторюсь, в ORM стараются решить как раз именно две эти проблемы: автоматическое превращение foreign key в связанную структуру данных (вместо post.user_id => post.user), и превращение обратного foreign key в список (вместо comment.post_id => post.comments).

Именно это мне и кажется причиной недовольства SQL среди разработчиков, и основной причиной попыток бегства с него. Чтобы спасти репутацию SQL, эти проблемы надо как-то элегантно решить - будь то на уровне БД или API доступа к ней.

Благодарю за внимание.?

UPD: Забыл, совсем забыл! Ещё NoSQL избавляет от ALTER TABLE. Разработчиков заколебало делать ALTER TABLE. Они привыкли одну строчку в коде поменять и перекомпилировать. А тут - несколько минут/часов форсмажора.

Оставить комментарий

Архив записей в блогах:
Хлопотно ли получить права в Израиле? Иностранные (США) есть, но давно просрочены.  Можно ли их использовать для получения новых, годных? Или теперь только выкинуть, и заново сдавать экзамены по вождению, по правилам движения? ...
Как я Вам говорила ранее, сегодня мы ждём встречи с matilda_i_ja и её сыном Олегом. Мы очень рады знакомству, такие крутые, живое общение в 1000 раз лучше общения в интернете! Первым делом отправились в гостиницу пообедать и отдохнуть с дороги! На ужин я приготовила крылышки и ...
Эти выходные, пожалуй, можно назвать идеальными, было всё: вкусная еда, прогулки, море, загар, бассейн, из культурной программы - одесский международный кинофестиваль, встреча с друзьями, приятный пикник у моря с очаровательными девочками из ...
Не раз и не два пользователи интернета изучали тюремные снимки, пытаясь определить самую красивую девушку, которой довелось побывать за решеткой. И похоже, что им всё-таки удалось определиться с именем той, кто заслуживает звание самой красивой преступницы XXI века. На фотографиях, р ...