What's left of NoSQL?
use-the-index-luke.com
use-the-index-luke.com
Which is not a bad thing, but I wish we could do it without the overhyped nonsense. It really is time for this business to grow the fuck up.
The "web generation" has brought us lots of great changes, I would have quit IT back in the 90's if the internet hadn't happened. But this immature attitude towards everything from technology stacks to how to run a company is really starting to grate.
For those of us that have been doing software development for a long time we would have heard countless vendors hyping their products. It's what they do and will continue to do. Normal developers have always ignored it and chosen the right tool for the job.
I actually find the anti-NoSQL crowd to be the immature ones and are often quite patronising as though I am some idiot for choosing a particular database. It's quite bizarre.
Reminds me of back in the 90's when object-oriented databases were going to rule the world and software was all going to be write-once-run-everywhere, or the early 2000's when static typing was the downfall of society. Meh. Every generation's got something like that.
As skeptical as I am of the latest trends, I sincerely hope that people stay excited about them, and keep using them. That bubbling cauldron of ideas does generate a lot of noise, but it also generates new ideas and progress.
1) the data challenges of yesterday's internet giants are the data problems for just about every 21st century enterprise tomorrow. We're at the start of / in the midst of an irreversible data explosion.
2) Established players not taking new technologies and upstarts seriously is never evidence of the threat not being real. We know that on the contrary our industry is characterized by constant disruption where established players for whatever reason do not consistently stay at the front line of innovation and tend to get leapfrogged. (as an analogy Google+'s lurch into social may be akin to Oracle's lurch into nosql. Does that mean social was not real?)
Bottom line: It all depends on what you're doing. But more and more of us will be dealing with more and more complex data in the years to come. Of that, I'm certain.
And people forget something important with SaaS. Data sovereignty. Here in Australia for example there are many enterprise companies who are forbidden from using ANYTHING that is hosted in the US due to the grey legal area e.g. Patriot Act. So in-house databases are absolutely still here to stay.
I would bet, however, that most of the clients that do business with Mongo or DataStax still intend on using/maintaining a relational system. I haven't really encountered many companies that's decided to completely dump their relational systems in favor of something else.
What you are arguing is that future people will value data security and performance less than scalability... Well, I doubt it, but my crystal ball is as useless as yours.
Or perhaps only think we have - I know a lot of developers who believe that an RDBMS should be kept at arm's length and only spoken to through an ORM, or who've never spent much time exploring what they're missing by never straying far from SQLite and MySql. These same folks seem to have a remarkable ability run into "big data" problems that "can't be solved by an ACID-compliant RDBMS" well short of the point where I'd only be thinking, "Huh, this DB's getting big enough that I might need to spend more time thinking about my indexing strategy."
I do agree wholeheartedly that more and more companies will be encountering situations where ACID proves to be a impediment to scalability in the future. But that's then, this is now, premature optimization is the root of all evil, and "Getting ready for a problem we might encounter in the coming years" is often just a fancy way of saying, "Solving a problem we don't actually have."
Also for all consumer apps, people value scalability over security and performance today, yesterday, last week, a year, 5 years ago, whatever. You should be using NoSQL for that. And B2B almost all business domains.
But I think it heavily depends on the specific use case what DB to use.
My problem with NoSQL is that you MUST know there won't be changing requirements:
Later you might need to do the equivalent of joining 3-4 tables. Then you have trouble... But I'm a coward that look both left and right before crossing a street.
Because it is schema less and document based you can trivially add new rich schemas to existing documents. And in the case of doing joins you can always do it in application layer or using DBRef or MapReduce. There are valid options that are still quite performant.
Just today I enjoyed explaining to a developer why his insert into a timestamp failed because of formatting, with a nice english error message. Thanks Postgres!
Whereas the same thing last year with Mongo just inserted the wrong date into a misspelled key and we didn't figure it out for days.
I thought the main advantage of document-oriented schema-less databases (I haven't used MongoDB but I have used CouchDB) was that they are supposed to give more flexibility in the early stages of projects.
NB Personally, I've moved to PostgreSQL and its JSON storage as then you get most of the benefits of both worlds.
Depends on your requirements, I guess. If you want to maintain even eventual consistency, any update that crosses document boundaries has to be thought about very seriously in order to avoid breakages in the face of concurrent modifications. So, ideally you design your documents such that any one logical operation only has to hit one document.
This is pretty easy for very simple tasks, but can get rapidly more difficult in the face of more complex or changing requirements. I suspect a substantial proportion of Mongo or Couch based applications simply ignore this problem, and are lucky that they don't have enough concurrent activity that stuff breaks frequently.
Using Postgres/JSON neatly avoids this problem because you get ACID back, and you can do cross-document updates all you like.
I agree with what you wrote.
But my point is that _changing_ requirements can screw you, if you find that you _later_ need relational capabilities.
One thing that surprised me though was the lack of a key player: Amazon. Their Dynamo paper was hugely significant and as a company they use eventually consistent stores for a whole swathe of products at scale.
Why mention Facebook and Google but omit this other major player, especially are their experiences tell a different story.
- downtime (lack of availability) is very expensive to them, both directly and also reputationally
- traditional ACID stores don't scale with writes whereas an eventually consistent store can achieve this
So I completely agree with you in short: Amazon have great reasons to pursue approaches based on eventual consistency.
If you build your app around a relational database and you need to scale up big then at some point you're going to hit a brick wall in terms of scaling out storage and/or writes. You either have to build sharding logic into your relational db app from the beginning(which is a pain that NoSQL saves you from), or else you have to re-architect your entire app when the time comes that you need to deal with scale. Many shops end up borrowing VC money to build out a team to re-architect their systems to handle web scale, but this can be avoided by thinking about data access patterns from the beginning and choosing a technology that can handle your future needs.
https://en.wikipedia.org/wiki/Scalability#Horizontal_and_ver...
And you are 100% wrong about MongoDB not scaling well. The stories you hear of people switching are never going back to PostgreSQL or MySQL they are going to the next level in scalability e.g. HBase or Cassandra.
Here's an example that explains how to get transaction-like guarantees from this kind of NoSQL data-store:
http://guide.couchdb.org/editions/1/en/recipes.html https://en.wikipedia.org/wiki/BigCouch
This is not something new it's a well established technique from the relational world called "event sourcing"
http://www.martinfowler.com/eaaDev/EventSourcing.html
when everything is a write you don't have to worry about conflicts or locks, so that's nice, plus couch is really good at scaling write thoughput with small documents.
I see they have since switched from PostgreSQL to Cassandra, though.
This limits your ability to write SQL queries because you can only query within a particular shard and that decreases the usefulness of mysql and makes it feel more like a nosql data-store. At that point you find yourself asking why didn't we just use a NoSQL store ? And often times the answer is "because we wanted to use something we were already familiar with". Sometimes people are willing to add a lot more complexity to their application just to allow themselves to avoid having to learn something new.
Because you still have the full ability to write general SQL within the shard. For many types of application this is useful.
IMHO Sharded MySQL very much belongs in the NoSQL camp.
Imagine you're LeanKit, or Fog Creek, and you run a kanban board as a service. Or a bug tracker, CMS, whatever. You have many customers, each of whom has no more than thousands of users and millions of items. There are many relationships between objects belonging to a given customer, but precisely zero relationships between objects belonging to different customers.
Shard using the customer identity as a key, and you have nicely spread-out data and the ability to do any query the application might need to, while still having a normalised schema.
There are plenty of other application whose schemas have this property, or almost have it. In my company, we make financial applications, and a lot of the data has very similar siloed ownership structure.
The one thing you can't do is reporting queries across your customers. That doesn't seem like a killer, though - it's normal to farm that stuff out to an offline reporting database even in single-server environments.
I personally find that SQL relational databases are not flexible enough for my application so I go with a polyglot persistence architecture that ties together a nosql key-value store with a graph database technology. This way I can use the cypher query language to access data relationally across all my shards while scaling writes and Big-data horizontally.
To each his own.
That sounds pretty powerful. Do you mind sharing more information about the data storage/querying stack you use?
http://pragprog.com/book/rwdata/seven-databases-in-seven-wee...
and grep for the phrase "polyglot persistence" you'll find some great information to get you started.
a video promo for the book: https://www.youtube.com/watch?v=bSAc56YCOaE
Graphs are perhaps the only area where NoSQL may beat relational databases for expressiveness, rather than alleged scalability or ease of use. I've read the documentation for Neo4j and Cypher, but never used them in anger, so i'd be really interested to know more about how they are actually used.
In particular, i would love to be able to make a comparison between a graph database and a relational database queried using recursive common table expressions, in the context of a real-world problem.
Graph databases can scale write throughput fine when those writes are being fed to it from a single source so it's best to have a service who's sole purpose is to keep the graph database in sync with the SOR. The graph should only store the data you actually need in order to get the queries that you want.
The specific queries in my domain are exactly the kind of thing I'm not supposed to talk about, but I will say you can do things like:
Give me 50 users who who live near me (lat/long bounding box), who I'm not already following, who I have not already sent a message to, who have at least two friends who also live near me, and who have matching tags, order by number of followers.
there are a bunch of great examples in this awesome book: http://www.amazon.com/Graph-Databases-Ian-Robinson/dp/144935...
The underlying data structures involved in Neo4J do help with performance on these kinds of queries, but in addition to that I find that for me the Cypher query language feels like a more concise and elegant way to ask for the data.
With RCTE it feels like I'm first asking the DB to construct a custom data structure, then I'm asking the DB to query that custom data-structure.
With Cypher it feels like I'm simply asking for the exact data I need by specifying the relationships and attribute characteristics that I care about.
This might just be a matter of taste, but if you start playing around with Cypher it just might grow on you.
However SQL doesn't make the problem of handling distributed databases magically disappear.
An example of distributed, horizontally scalable database supporting strong consistency and offering an SQL interface:
http://static.googleusercontent.com/media/research.google.co... and a layer above: http://static.googleusercontent.com/media/research.google.co...
It still requires the users to carefully organize their data, according to a hierarchical data model provided by the database.
There is a mapping between a hierarchical relational model and a column store model. (EDIT: see one possible mapping in http://www.cidrdb.org/cidr2011/Papers/CIDR11_Paper32.pdf)
The article skims over this aspect, as if all that matters is the syntax of the query language.
Whenever I see these "SQL vs NoSQL" arguments, I always have to wonder: Why one over the other? A lot of projects can benefit from both and there's no reason you absolutely HAVE to use one or another. It's perfectly reasonable (and probably ideal) to use more than one storage system in your projects.
If you have a bunch of nails to hammer in and bolts to tighten, you don't choose just a hammer or a wrench to do that job...you grab both and use each for what they do best.
And you've been running this application in production how long?
Prior to this backing up was a messy process.
The "traditional" approach is to use Oracle/SQL Server/MySQL for storage, SQL and/or ORM as an API, and single-server tables-with-relationships as an architecture. Back in the early 2000s, everybody did this. Sure, there were a few performance-minded exceptions that went with sharding or master-slave architectures instead, but those were exceptions.
And single-server architectures tend to behave badly at medium loads. Spend the market rate for a genius DBA, and they still behave badly at high loads. The next step is a 32-core 128GB RAM monstrosity that costs an order of magnitude more than what eight 4-core 16GB servers would cost.
Most NoSQL solutions came with a new architecture. You had the MongoDB flavor of distributed storage, or the BigTable flavor of distributed storage, or the CouchDB flavor of distributed storage, and so on. Properly implemented distributed storage eats high loads for breakfast: just add more servers. This is a good thing.
My issue with the NoSQL movement is that they threw away the baby with the bath water. They threw away the single-server relational architecture, which was a nice change, and they also gave up the old battle-hardened storage engines and the highly expressive SQL language and replaced them with only-recently-experimental engines and ad hoc lean APIs.
It takes time for a storage engine to mature. To have all its performance kinks ironed out and all its bugs smoked out. I still remember the brouhaha around MongoDB persistence guarantees, or the critical data loss bugs in CouchDB.
And the lean APIs just forced back all the querying logic into the application, with all the filtering and the manual indexing and the joins and the approximate but ultimately incorrect implementations of whatever subset of ACID was required at the time. This wasn't an entirely bad thing: it certainly made many developers aware of the performance implications of some joins or transactions. But when you need to write a JOIN or GROUP BY or BEGIN TRANSACTION that you know will scale properly, and there's no API support for it ? Feh.
I'm a huge fan of the CouchDB architecture. Distributed change streams, with checkpointed views and cached reductions. But I have been burned by the CouchDB storage engine (can you say "data corÊ–NÑ %ñXtion" ?) and I see no point in bending knee to the laconic CouchDB API. So I took the CouchDB architecture and reimplemented it with a PostgreSQL back-end. It's _faster_ (don't underestimate the cost of those HTTP requests), I have trust that after PostgreSQL's decade-long history all threats to my data are long gone, and I can always whip out an SQL query when I do need it.
It's nice to see so many NoSQL solutions migrating back to an SQL-like API and gaining enough maturity to keep your data safe. In the near future, I expect them to be nothing more than "Architecture in a box" solutions for when you don't want to implement specific architectures in SQL. And I expect more and more "architecture plugins" to become available: with a library, turn a herd of SQL databases into a distributed architecture of type X.
can you provide more details on this? is there a public repo?
A `Stream` corresponds to change events (I'm not sure these even had an official name in CouchDB).
A `Projection` corresponds to a design document.
The various `View` implementations are optimized for various aspects of CouchDB views, with `MapView` being the literal equivalent of a CouchDB view. Except they can be chained (you can apply a map to a map).
Unlike CouchDB, views are evaluated eagerly, though the `HardStuffCache` (and other planned `Cache` implementations) are evaluated lazily on a per-document basis.
In a production environment they should be well tested before deployed to the live system. That plus backups should help prevent calamities.
There are still possibilities of deleting the data whether through the ORM or direct SQL, both could be easily accomplished so test before deployment and keep regular backups in case of disaster.
Most of the criticisms about ORM's come from people who have never used them, beyond maybe working through a Rails chat-room tutorial once upon a time. It really has nothing to do with "abstracting away the database".
As the name indicates, Object-Relational Mapping is merely about reducing the boilerplate required to map a relational schema to programming language objects. If you do that mapping by hand, then you have to make decisions when a table/object has relationships. Picture a CUSTOMER table, which has a foreign key relationship to an ADDRESS table. When your application loads a "Customer" object:
[1] You could "eager fetch", meaning that you go ahead and retrieve all of the ADDRESS rows related to that CUSTOMER, and attach the Address objects to the Customer object. Eager fetching is wasteful and leads to poor performance, because you're hammering your database for values that you often don't ever use.
[2] You could "lazy load"... meaning that your Customer object has an "addresses" field, but you wait until some code tries to use that field before you actually query the ADDRESS table to populate it. This is much better design, but complicates things. The lazy load logic has to go somewhere. You either have to ensure that every piece of code using that object is aware of the lazy load pattern, or you have to stuff database logic into the "getter" method for each lazy-loaded field.
ORM's give you highly-performant lazy loading, without the buggy boilerplate suggested by #2 above. Moreover, enterprise-class ORM's typically handle caching for you, to avoid hitting the database unnecessarily. Monitoring the state of objects to notice when they've gone stale due to changes on the database side, etc.
Lastly, for complex queries, most ORM's have a query language (e.g. JQL, HQL, etc) that is nothing more than a VERY THIN wrapper around SQL. It merely smooths out differences between various vendor dialects. You're not abstracted away from the database, you still very much need to understand SQL and the underlying structure of your data.
A good ORM will likely default to lazy loading but give you good options for eager retrieval when you know you're going to need it.
And it's also much more convenient to call a find() method than to concatenate together a (vendor-specific) connection string and query string, and iterate over a result set object.
That's good to hear! Though in my experience of interacting with people who have learned development in last 3-5 years, many of them are very oblivious to basic database concepts. They mostly think in terms of the object in the code, relying on the framework to take care of the database. It might even generate the sql that they just need to execute. But anyone who's worked with production database from before the advent of frameworks like Rails etc. knows that the only thing worse than messing up an sql statement is running auto generated sql.
In my experience, this lazy/eager is the main reason I don't like rich ORM mappings. I usually don't map collections and don't map foreign keys. If I need to fetch something, I just do it. If I need to return a result of a complex query, I just define datatype for it. In general, my ORM just converts recordset to object, and that's it it, besides simple record level CRUD operations. One record operations like findByPK or deletByPK or updateByPK are fine, but for anything else I prefer writing SQL, instead of suffering with some ORM specific SQL replacement or, $deity forbid, some api. SQL is as good DSL as you can get for RDBMS access, and is fairly portable between different programming langagues and ORMs, so no reason not to use it. But many
There's been a difference with this "technology cycle" though, there have been some prominent, well grounded voices from the start of this cycle.
That's a good thing.
That wasn't the case for other cycles - the thin vs fat client cycle, the DAS vs NAS cycle etc. etc.
EDIT: i'm not saying NoSQL has no application. I earn a paycheck working with a huge graph db (and it's nothing to do with "social", yay!), and have previously been a heavy user of Cassandra.
Perfect!
Indicating that they were NOT within the current paradigm of SQL databases was the only way to go.
SQL is a QUERY language. NoRDBMS would be slightly less moronic...
Thbbft!
IndexedDB is fine for storing JSON objects, etc. but a relational database with SQL query syntax, indexes, etc. more powerful and means less code to write. With IndexedDB one has to reinvent the wheel to just get basic query features.
WebSQL is not deprecation, the W3C Working Group Note actually says:
'This specification is no longer in active maintenance
and the Web Applications Working Group does not intend to
maintain it further'.
WebSQL is only available in Webkit based Browsers (Safari, Chrome) which means most mobile browsers.
As SQLite is in public domain, no company would "loose their face" if they choose to use it. They could fork off SQLite and change the SQL query syntax (parser) to whatever the W3C finds suitable. https://www.sqlite.orgMozilla Firefox and FirefoxOS both already ship SQLite for years and can be accessed by its internal JavaScript API. And several Microsoft products already use it anyway (e.g. Forza Xbox games). Microsoft has of course also various other SQL database libraries like MS Access JetRed, MS Outlook JetBlue and SQL Express.
We had a discussion about it recently: https://news.ycombinator.com/item?id=7574754
The new hip things is "NewSQL" (http://en.wikipedia.org/wiki/NewSQL ). For example Facebook, Google Ads, etc. are powered by MySQL's InnoDB database engine. I would go as far as count SQLite to this group.
We would need a movement to convince Mozilla to finally add WebSQL to Firefox and FirefoxOS.
1. http://www.w3.org/TR/webdatabase/#web-sql
Edit: here is Mozilla's rationale for not supporting WebSQL: https://hacks.mozilla.org/2010/06/beyond-html5-database-apis...
I believe SQLite caused issues with MS, but Mozilla was more philosophically opposed to SQL as being legacy tech. Which is understandable but unfortunate when the standard had momentum and SQL is so well-understood.
On the backend, that's more or less OK, although one of the value propositions of ORMs is that they make it somewhat easier to change databases later by reducing the amount of product-specific SQL that has to be rewritten. On the web, however, it's totally unacceptable. Sites are expected to keep working between multiple browsers and across multiple browser versions. To achieve that level of interop would have required someone to sit down and write a detailed specification of the dialect of SQL that should be supported on the web, and for browser vendors to take the time to implement it. In practice people weren't willing to spend the time doing either of those things; the level of buy-in was enough to fork sqlite but no higher.
Eventually the web might get something like WebSQL. But the way it will happen will be for people to implement SQL in js on top of IndexedDB. If that proves popular but has issues (e.g. with performance) then there will be renewed impetus to do a proper job of a WebSQL specification.
Many SQL databases support multiple SQL dialects.
Firefox certainly ships with SQLite and even their IndexedDB implementation is based on top of it internally (the irony): https://plus.google.com/+KevinDangoor/posts/PHqKjkcNbLU
Microsoft has MS Access JetRed, MS Outlook JetBlue and SQL Express SQL Databases that ship already with Windows and/or Office and are SQL-92 compatible. It should be trivial for them to figure out which SQL DB engine would fit best and integrate it in IE 12.
Most Microsoft tools that need an embedded engine use ESE(Jet Blue), which is bundled with Windows.
For third-party desktop developers, the replacement is SQL Express LocalDB. For WinRT developers, Microsoft has paid the SQLite developers to port it over, so that it passes Store validation.
Windows Phone still uses SQL CE, but the only interface to it is LINQ-to-SQL. So Microsoft could conceivably swap out the backend at any time.
IndexedDB is kinda nasty to work with directly, but there are fairly good libraries on top of it. http://www.taffydb.com/ looks great for complex queries. One I work on http://pouchdb.com provides syncing (also works with WebSQL)
WebSQL is also pretty nasty to work with, hand crafting SQL string in the browser for one just feelds weird, even yesterday I had a bug filed which related to the internal SQLLite implementation (the entire reason WebSQL is a no go is it has one implementation, Richard Hipp would now own web storage)
I havent seen much support from webSQL, even between those of us who actually use it most are just waiting for it to die, indexeddb in safari is that final nail
localStorage has been well supported over all browers since IE8... It's interface IMO is a perfect fit in JavaScript... with the one exception of not being callback driven...
However, for most web development SQL is seriously not good. You end up with hundreds of loosely coupled tables which constantly change their structure for new features. Half dozen of joins on every request. Hundreds of lines of SQL. Constant pain. And it's not like you cared so much for the consistency - if once a year three comments disappear from your web site, so what?
And it's painful to make SQL multi-master.
For (the most of) web development document databases are so much better. MongoDB is pretty nice because it makes hundreds of lines of SQL with ten files of code redundant - all per one complex document.