GraphQL N+1问题及DataLoader解决方案

James Park | 2026-07-30T13:34:00 | JavaScript, Database

GraphQL的N+1查询问题分析,以及使用DataLoader进行请求合并和缓存的实践

# GraphQL N+1问题及DataLoader解决方案 上了GraphQL之后发现数据库查询量暴增,一个列表接口居然发了101条SQL。经典的N+1问题。 ## 问题场景 ```graphql # 查询100篇文章及其作者 query { articles(limit: 100) { title author { name avatar } } } ``` ```javascript // resolver里每篇文章都查一次author var resolvers = { Article: { author: function(article) { // 这个方法会被调用100次! return db.query('SELECT * FROM users WHERE id = ?', [article.authorId]); } } }; // 结果:1次查articles + 100次查users = 101条SQL ``` ## DataLoader解决 ```javascript var DataLoader = require('dataloader'); // 创建批量加载器 function createUserLoader() { return new DataLoader(function(userIds) { // 把100次查询合并成1次 return db.query( 'SELECT * FROM users WHERE id IN (?)', [userIds] ).then(function(users) { // 按照传入的ID顺序返回结果 var userMap = {}; users.forEach(function(u) { userMap[u.id] = u; }); return userIds.map(function(id) { return userMap[id]; }); }); }); } // 每次请求创建新的loader实例 app.use(function(req, res, next) { req.loaders = { user: createUserLoader() }; next(); }); // resolver改用loader var resolvers = { Article: { author: function(article, args, context) { // DataLoader自动合并和缓存 return context.loaders.user.load(article.authorId); } } }; // 结果:1次查articles + 1次批量查users = 2条SQL ``` **关键点**:DataLoader要每次请求创建新实例,否则不同请求之间会共享缓存,导致数据错乱。

← Back to Blog