当前位置:首页>java>这行 C# 代码差点让我被开除

这行 C# 代码差点让我被开除

  • 2026-10-21 13:28:47
这行 C# 代码差点让我被开除

上周客户反馈系统卡死,CPU 直接飙到 100%。

排查了半天,发现是一行看起来人畜无害的 LINQ 代码惹的祸。

这行代码在测试环境跑得好好的,一上生产就炸了。原因很简单:测试库 100 条数据,生产库 100 万条。

问题代码

先看这行"杀手代码":

// 查询订单总金额大于1000的用户 var users = db.Users     .Where(u => db.Orders.Where(o => o.UserId == u.Id).Sum(o => o.Amount) > 1000)     .ToList();

看起来没毛病对吧?逻辑很清晰:找出订单总金额超过 1000 的用户。

但这行代码会让数据库对每个用户都执行一次子查询。

用户表 1 万条,订单表 10 万条,实际执行的查询次数:1 万次!

这就是经典的 N+1 查询问题,LINQ 写法不当最容易踩的坑。

正确写法

用 GroupBy + Join 改成一次查询:

// 先聚合订单数据 var userAmounts = db.Orders     .GroupBy(o => o.UserId)     .Select(g => new { UserId = g.Key, Total = g.Sum(o => o.Amount) })     .Where(x => x.Total > 1000)     .ToList();  // 再查用户信息 var userIds = userAmounts.Select(x => x.UserId).ToList(); var users = db.Users.Where(u => userIds.Contains(u.Id)).ToList();

或者用更简洁的 Join 写法:

var users = (from u in db.Users              join o in db.Orders on u.Id equals o.UserId into orders              let total = orders.Sum(o => o.Amount)              where total > 1000              select u).ToList();

性能对比

同样的数据量(用户 1 万,订单 10 万),两种写法的差距:

写法
SQL 执行次数
耗时
CPU 占用
错误写法(子查询)
10001 次
45 秒
100%
正确写法(GroupBy)
2 次
0.3 秒
5%

性能提升 150 倍!

为什么会这样

LINQ to SQL/EF 的执行机制:

  • 延迟执行
    :LINQ 表达式不会立即执行,调用 ToList() 时才真正查数据库
  • 表达式树转换
    :EF 会把 LINQ 转成 SQL,但嵌套查询会被翻译成子查询
  • N+1 问题
    :外层每遍历一条记录,内层就执行一次查询

用 SQL Profiler 抓一下就能看到,错误写法生成的 SQL 类似这样:

-- 对每个用户都执行一次! SELECT SUM(Amount) FROM Orders WHERE UserId = 1 SELECT SUM(Amount) FROM Orders WHERE UserId = 2 SELECT SUM(Amount) FROM Orders WHERE UserId = 3 ... 重复 1 万次

如何避免

记住这几个原则:

1. 避免在 Where 里嵌套查询

// 错误:Where 里套 Where .Where(u => db.Orders.Where(...))  // 正确:先 GroupBy 聚合,再 Join

2. 用 Include 预加载关联数据

// 一次性加载用户和订单 var users = db.Users.Include(u => u.Orders).ToList();

3. 检查生成的 SQL

// EF Core 开启日志 optionsBuilder.LogTo(Console.WriteLine);  // 或者用 ToQueryString() var sql = query.ToQueryString();

4. 大数据量用原生 SQL

复杂统计查询,直接写 SQL 可能更清晰高效。

总结

LINQ 很优雅,但写不好就是性能杀手。

记住一句话:能用一条 SQL 解决的,别让它变成 N 条。

下次写 LINQ 前,先想想它会生成什么样的 SQL。

觉得有用的话,点个赞收藏一下~

#程序员 #开发 #代码 #CSharp #LINQ #性能优化

最新文章

随机文章