Последний программный пост собрал тревожное количество комментов. Среди трюизмов вроде "а где ж у вас ACID", "а у меня биллинг отлично на SQL работает", "опять велосипеды изобретаете" проскочило всё-таки несколько повторяющихся замечаний, которые, на мой взгляд, нуждаются в пояснении:
1. А как же производительность и масштабирование? NoSQL ведь применяют именно для них. Личные желания программистов вторичны!
2. А в вашем NoSQL выборки всё равно делать нельзя, вот!
Первый пункт повергает меня в грусть. По-моему, он логично вытекает из всего того, о чём я говорил. Программисты получают больше контроля над структурами данных => у них больше доступных способов реализовывать масштабирование и оптимизировать производительность => PROFIT. Т.е. интуитивные желания программистов игнорировать не следует - интуиция иногда часто подсказывает им способ решения практических проблем.
Второй пункт повергает меня в грусть ещё большую. Разумеется, как я уже говорил, "выборки" в этом ихнем NoSQL делать можно ничем не хуже, чем в реляционных БД. Покажем на примере.
Допустим,
в проекте возникла задача получить все комменты, написаные конкретным автором.
Для реляционной БД: если индекса по полю comment.author_id нет, то при выборке случится fullscan, т.е. O(n). Построение индекса занимает, ясен перец, O(n) и никак иначе. Зато с индексом (B-Tree, разумеется, потому что Hash -
говно) каждый поиск будет стоить O(log n).
Для NoSQL же: если индекса нет, то при выборке придётся реализовать тот же fullscan, т.е. O(n). Построение "индекса", т.е. списка ссылок на комменты вида:
class User {
// ...
List writtenComments;
// ...
}
занимает тоже, собснно, O(n). Зато "поиск" по этому "индексу" будет занимать O(1) - мы фактически возьмём список как есть. То есть, возвращаясь к п.1, освободив чистый список из плена индексного B-дерева, мы не только не проиграли, но и получили даже некоторый прирост производительности при "выборке".
Да, в SQL это можно сделать "одним запросом", да и константные множители с этими O() будут поменьше - но при этом у вас почти нет гарантий, каким образом и сколько времени будет выполняться этот запрос и что будет происходить с приложением во время его работы (mysql table lock, anyone?). А если вы уже имели неосторожность заняться шардингом - у вас не только запрос станет "не один", но и сопроводительные танцев с бубном для синхронизации потребуются.
SQL-базы, как ни парадоксально, являются всего лишь подмножеством NoSQL-баз. Ясное дело, для надмножества реализуемы все те же алгоритмы, что и для подмножества - никакого сверхъестественного ингридиента в RDBMS нету. Другое дело, конечно, что в более общем случае всё приходится делать самому, плюс сложнее реализовать такие вещи, как ACID - но это та цена, которую приходится платить за свободу.
Основная концептуальная разница между RDBMS и NoSQL, которую почему-то плохо понимают (возможно, потому что про неё не совсем внятно рассказывают), заключается в том, что в первых принято хранить данные в "правильном" формате (что упрощает запись и поддержание целостности), а во вторых - в том формате, который проще и быстрее показать. Т.е. это логичное развитие идей денормализации - но в то же время не доходя до кэширования готовых страниц.
Надеюсь, ни у кого не возникло ощущения, что я пропагандирую NoSQL. Мне всего лишь интересно проанализировать феномен, изложить свои соображения и развеять некоторые популярные заблуждения.