?

Log in

Зачем NoSQL программистам - отражение жизни в экране монитора [entries|archive|friends|userinfo]
отражение жизни в экране монитора

[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Зачем NoSQL программистам [Jun. 10th, 2010|11:58 am]
отражение жизни в экране монитора
[Tags|]

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

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

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

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

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

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

Так чем ж оно лучше 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 программисту приходится выворачивать мозг наизнанку. Он не чувствует привычного контроля над структурами данных.  Знакомые алгоритмы искажаются. Более того, ему не совсем понятно, для чего это нужно.

Зато смотрящему с RDBMS-башни наблюдателю всё, конечно, понятно. Реляционная система хранения оптимизирована для запросов (буква 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. Они привыкли одну строчку в коде поменять и перекомпилировать. А тут - несколько минут/часов форсмажора.

UPD-2: Вторая серия - http://rainman-rocks.livejournal.com/121163.html

UPD-3: ВНЕЗАПНО выяснилось, что практикующие со мной тоже в целом соглашаются: http://ivan.begtin.name/2010/06/11/%D1%82%D0%B5%D1%85%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5-%D0%BF%D1%80%D0%BE-nosql-%D0%B2-%D0%B3%D0%BE%D1%81%D1%81%D0%B5%D1%82%D0%B8/
linkReply

Comments:
(Deleted comment)
[User Picture]From: asinitsyn
2010-06-10 01:17 pm (UTC)
Написал свое мнение по этому поводу

http://asinitsyn.livejournal.com/33307.html

Вкратце - последствия описаны верно, но у меня свой взгляд на причины.
(Reply) (Parent) (Thread)
From: octo47
2010-06-10 11:21 am (UTC)
отлично. прямо в точку.
(Reply) (Thread)
[User Picture]From: gabaidulin
2010-06-10 11:27 am (UTC)

Отличный пост.

Но ведь были такие попытки(объектные стораджа, например, cache db)? Да и Завалишин чего-то подобное делает в своем Фантоме.

Но не пошло. Как вы думаете, почему?
(Reply) (Thread)
(Deleted comment)
(Deleted comment)
[User Picture]From: vitus_wagner
2010-06-10 11:28 am (UTC)
Это из серии "я хочу чтобы у меня все было, и мне за это ничего не было". А так не бывает. SQL хорош тем, что под ним лежит хорошая математика - реляционная алгебра. Эта математика накладывает на возможности представления довольно большие ограничения. Но эти ограничения являются платой за возможность эффективно оптимизировать запросы.

К сожалению, большинство разработчиков, хватающихся сейчас за NoSQL никогда в жизни не слышали слова CODASYL. Поэтому не знают, что история баз данных начиналась с объектно-ориентированных БД, где не было никаких ограничений. Но и искать было крайне затруднительно.
(Reply) (Thread)
From: zhengxi
2010-06-10 02:14 pm (UTC)
> Но эти ограничения являются платой за возможность эффективно оптимизировать запросы.

Вот взять тот же пример с постами и коментами.
Там ровно наоборот получается - для реаляционного решения нужен индекс по всем коментам, поиск по которому не будет лучше логарифмического (а комментов много, так много, что они и на один сервер могут не поместиться).
При этом post_id используется только для связи поста и коммента.
Есть RDBMS которые это "поймут" и эффективно соптимизируют до O(1), до (неявного, скрытого от автора SQL-запросов) хранения указателей на комменты рядом с постом ?

> К сожалению, большинство разработчиков, хватающихся сейчас за NoSQL никогда в жизни не слышали слова

Еще есть слово IMS, IMS is reportedly IBM's highest revenue software product, and it continues to grow.
Вполне такой NoSQL.
(Reply) (Parent) (Thread) (Expand)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
[User Picture]From: metaclass
2010-06-10 11:34 am (UTC)
Я не понимаю, почему в SQL до сих пор нет типа поля результата "список"?
Т.е. делая запрос к таблице, мы одно из полей делаем подзапросом, выбирающим список из связанной таблицы и так его и возвращаем. Конечно, придется массово переделывать API, придумывать, как это все дело отобразить(и вставлять тоже) но "выбрать объект и его подчиненные объекты одним запросом" было бы весьма удобно.
(Reply) (Thread)
[User Picture]From: plumqqz
2010-06-10 11:35 am (UTC)
Ну как нет. Есть. Оракловые курсоры. В постгресе мне пришлось эмулировать.
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: avnik
2010-06-10 11:36 am (UTC)
На самом деле NoSQL с сериализоваными объектами будет рулить на этапе гаражного стартапа, когда только раскапываешь предметную область.
(дизайнит базу, которую еще раза три прийдется переделать на этом этапе просто дорого -- и по трудозатратам (если самому), и по деньгам (если нанимать DBA со стороны)

Да и индексы по общему полю в разных объектах иногда доставляют.
(zodb/zope например позволяют индексировать f(x) где x произвольный объект)
(Reply) (Thread)
[User Picture]From: stasikos
2010-06-10 04:23 pm (UTC)
Есть несколько странных "гаражных стартапов" типа Twitter, которые начинали с SQL и ушли в NoSQL, я вот почитал-почитал тут кругом и так и не понял почему.
(Reply) (Parent) (Thread) (Expand)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
[User Picture]From: fantaseour
2010-06-10 11:42 am (UTC)
Класс.

Я на это обратил внимание, когда читал книжку Фаулера, про UML. Когда строишь диаграммы классов у тебя направленная ассоциация, это указатель. А когда переводишь это в таблицы, указатель, как правило разворачивается.

Т.е. был пост и массив ссылок на комменты, а появились комменты с id поста.
(Reply) (Thread)
[User Picture]From: norguhtar
2010-06-10 12:00 pm (UTC)
С моей точки зрения психический дискомфорт наблюдается только у тех кому плохо или никак вообще не читали теорию баз данных, а именно реляционную модель и реляционную алгебру. Просто банально парадигма другая.
(Reply) (Thread)
[User Picture]From: metaclass
2010-06-10 12:05 pm (UTC)
Мне никак не читали, но после того как я это дело осилил, я стал ярым адептом реляционных моделей :) Но попытки натянуть сову на глобус использовать ORM не оставляю.
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: cd_riper
2010-06-10 12:47 pm (UTC)
интересный пост, спасибо
(Reply) (Thread)
[User Picture]From: alexclear
2010-06-10 12:49 pm (UTC)
Мне кажется, Вы некоторым образом дрочите на умные слова и понятия, что снижает ценность Вашего текста до нуля.
(Reply) (Thread)
[User Picture]From: rainman_rocks
2010-06-10 12:56 pm (UTC)
Мне кажется, Вы некоторым образом неправы. Умные слова здесь всего лишь средство. Я б затруднился свою мысль выразить при помощи неумных слов.

(Reply) (Parent) (Thread) (Expand)
(Deleted comment)
(Deleted comment)
(Deleted comment)
(Deleted comment)
[User Picture]From: suvlehim_takac
2010-06-10 01:00 pm (UTC)
отлично написано, буду перечитывать на досуге
(Reply) (Thread)
[User Picture]From: kuntashov
2010-06-10 01:26 pm (UTC)
Есть еще такая особенность SQL, связанная с этой самой Q - его декларативность, в то время как думать человеку проще императивно, в терминах "сделай это, потом сделай то".

Более-менее сложные запросы отлаживать на порядок сложнее аналогичных (по выдаваемому результату) императивных конструкций.

Поэтому ORM - это не только инструмент делать "структуру хранилища, отражающую их предметную область", но возможность решать задачу императивно (что многие с радостью используют, чаще закрыв глаза на вопрос производительности).
(Reply) (Thread)
[User Picture]From: norguhtar
2010-06-10 01:48 pm (UTC)

Поэтому ORM - это не только инструмент делать "структуру хранилища, отражающую их предметную область", но возможность решать задачу императивно (что многие с радостью используют, чаще закрыв глаза на вопрос производительности).

Это скорее инструмент взвалить эту головную больше ORM или тех кто этот самый ORM могут настроить.
(Reply) (Parent) (Thread)
[User Picture]From: dz
2010-06-10 01:41 pm (UTC)
Всё это можно сказать куда короче: гемора с SQL много, а что мы за него получаем - ясно не всем.
(Reply) (Thread)
[User Picture]From: metaclass
2010-06-10 01:43 pm (UTC)
Как минимум, мы получаем решение, которое могут понять большинство программистов и сторонних программ. А не непонятно чо выпускаемое непонятно каким стартапом.
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: inv2004
2010-06-10 02:30 pm (UTC)
Вот с ходу не ясно:
почему Post { User, Comment[]}, а не User { Post[] {Comment[]} } например?

(Reply) (Thread)
[User Picture]From: rainman_rocks
2010-06-10 02:34 pm (UTC)
Несущественно, вообще говоря. Можно и так и эдак, как в конкретной задаче удобнее. А скорее всего будет двусторонная связь.
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: b00ter
2010-06-10 04:35 pm (UTC)
Хорошо написал.
Правда программистам редко дают возможность выбирать. За исключением некоторых случаев.
(Reply) (Thread)
[User Picture]From: rainman_rocks
2010-06-10 04:39 pm (UTC)
В полной мере - редко. Но у программиста часто есть возможность прополоскать мозги лиду/манагеру до той или иной степени.
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: juan_gandhi
2010-06-10 11:24 pm (UTC)
O,так, короче, вся промлема в лемме Ионеды, в отсутствии сопряженных функторов степени и произведения. Ето поправимо, в теории.
(Reply) (Thread)
[User Picture]From: rainman_rocks
2010-06-11 06:51 am (UTC)
Вспоминается хороший анекдот: "теоретически, сынок, у нас есть два миллиона. А практически - две бляди в доме".
(Reply) (Parent) (Thread)
[User Picture]From: boombick
2010-06-10 11:35 pm (UTC)
Молодец, Костик, отличный пост!
Как раз начинаю смотреть в сторону NoSQL-решений именно из-за избыточности SQL-а. Проанализировав код, который я пишу, пришло понимание того, что SQL-я мне слишком много :)
(Reply) (Thread)
[User Picture]From: latrommius
2010-06-11 06:58 am (UTC)
Ну или тупо ещё один дополнительный запрос (что неприятно для производительности).

Весьма спорно.
А вообще, спасибо за ссылки в тексте.
(Reply) (Thread)
(Deleted comment)
[User Picture]From: rainman_rocks
2010-06-11 09:35 pm (UTC)
У меня? Популярный блог? Полноте, до позавчерашнего дня включительно здесь три калеки с половиной тусовались. Начиная с завтрашнего - будет четыре с половиной.

Это был однократный эффект, не уверен что смогу/захочу его закрепить.
(Reply) (Parent) (Thread)
From: grey3
2010-06-12 07:52 pm (UTC)

SQL vs NoSQL: а как всё-таки лучше?

Написал длинный вопрос в своём ЖЖ: SQL vs NoSQL: а как всё-таки лучше?

asinitsyn > "Как DBA с опытом,"
> zabivator > "3. Я программист, который занимается разработкой движков СУБД"
Хочу задать вопрос одновременно ОБОИМ собеседникам: как в реляционных СУБД, например MySQL, эффективно решить заданный в посте rainman_rocks "Зачем NoSQL программистам" пример: эффективно извлечь несколько записей с подзаписями-списками?


Хотелось бы получить заодно и ваш ответ там.
(Reply) (Thread)
From: grey3
2010-06-14 07:05 pm (UTC)

Re: SQL vs NoSQL: а как всё-таки лучше?

Там же (SQL vs NoSQL: а как всё-таки лучше? Итоги дискуссии ) приведена идея, как можно убрать недостатки SQL на примере, аналогичном вашему, и соответственно лишить NoSQL части преимуществ "очевидности". Небольшая оптимизация базы и драйверов, плюс хороший пример в документации - и многие программеры поймут, как просто и эффективно реализовать вложенные массивы/списки в SQL. :)
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: wolverrum
2012-04-21 11:38 am (UTC)
Хорошие грибы.
Много желающих, судя/ по каментам.

(Reply) (Thread)