4 ms·
It does not have that problem baked into it since it relies on resolvers. It would have to be a choice to have that problem.
by rtorr 6y ago
It does not have that problem baked into it since it relies on resolvers. It would have to be a choice to have that problem.
- ubercore 6y agoA straightforward implementation certainly would have that problem. You have to put a decent amount of effort in to reduce query count to fill a nested query graph.
- rtorr 6y agoNot really. A straightforward implementation has nothing to do with database usage. A resolver is an endpoint. You can leverage that like you can in any other http backend server.
- ubercore 6y agoNested resolvers can incur extra queries as you follow down the tree, unless you put extra effort into pre-fetching what child nodes need, or some kind of data loader as GP suggested. query { parent { child { field } } } A straightforward, naive implementation would resolve `parent`, then a resolver for `child` would execute, then for `field`. If `child` is a table linked by an FK, a second query would be executed, unless you pre-fetch the results through a join when resolving `parent`.
- wongarsu 6y agoIn a GraphQL API backed by a single database you could write resolvers that analyze the entire query and rephrase it as a single database query. But I'm not aware of anyone doing this. The common/straight forward solutions resolve each layer after each other, which you can optimize to 1 DB query per layer of the GraphQL query using dataloader patterns, with further optimizations for known common patterns.
- rtorr 6y agoYeah, I think there is a perception that people want direct queries into their database, but that is actually not the correct way to think about graphql.
- topspin 6y ago> But I'm not aware of anyone doing this. I have, for a bespoke internal application. PostgreSQL is actually capable of expressing GraphQL queries as (rather elaborate) SQL queries. You end up generating queries that use a lot of LATERAL sub-selects. The risk is generating queries with poor performance, and that risk is high enough that I don't think this is a viable approach for complex applications. Which is a shame.
- heneryville 6y agoSome people do try to generate a single SQL query that covers all nested resolves. See Join Monster [1]. I'm skeptical that it would ever work well in SQL. Datomic, being close to a graph database, makes constructing a single deep query for all resolvers fairly straight forward. This is the approach my team is taking now. It's worked quite a bit better than my DataLoader biased intuition suggested. [1] https://join-monster.readthedocs.io/en/latest/ https://join-monster.readthedocs.io/en/latest/
- allknowingfrog 6y agoThis seems a little pedantic. It may not be literally required by the technology, but GraphQL certainly makes it easier to introduce N+1 queries than a traditional REST API.
- a-priori 6y agoIn practice, I find REST APIs also have N+1 problems the same way GraphQL does. They just get spread across multiple requests.
- Groxx 6y agoIf anything I'd say REST is dramatically worse in this respect. There's no structure for nested queries (or anything except thing/:id really), so the only broadly compatible option is to pull every piece as a separate GET request. Sure, you can use query params... but there's no implied support nor semantics, so one site will do one thing and another will do something from a completely different universe of architectural patterns, while a third will just have nothing, and there's no way to reconcile those in a consistent way.
- travellingprog 6y agoYou don't need to have 1:1 equivalence between API resources and database models, though. For example, you can create an API resource called TweetActivity, and then the backend code for GET /tweet-activity could put together a database query that grabs all the tweet likes, comments and basic commenter info (name, profile image), from different database tables, into a single new object. You can give that object the same ID as the tweet itself, and you can put a cache layer around that endpoint to, for example, save that response for the next 1 minute. That being said, one thing you give up is providing a standard way for the client to specify which fields it needs returned. For example, a client might want to dig deeper into the commenter profile info. GraphQL's resolvers architecture opens up that possibility immediately.
- Groxx 6y ago