性能优化:如何实现SQL查询构造场景下的并发Builder模式
前提:多个BuildXXClause方法之间无逻辑依赖,无需使用彼此的生成结果,这是并发改造的基础
核心实现思路
通过惰性执行+任务收集的方式改造Builder内部逻辑,链式调用阶段不实际执行SQL片段生成逻辑,仅将每个构建操作封装为任务存入内部队列,调用最终Build()方法时统一启动所有任务并发执行,待全部完成后拼接结果生成最终对象,全程保留原有链式调用写法。
具体实现示例(C#)
public class PersonQueryBuilder { // 存储最终生成的所有有效SQL查询片段 private readonly List<string> _sqlClauses; private PersonQueryBuilder(List<string> sqlClauses) { _sqlClauses = sqlClauses; // 此处可添加SQL片段拼接、语法校验等后续逻辑 } public class Builder { // 收集所有待执行的构建任务,每个任务返回对应生成的SQL片段 private readonly List<Func<string>> _buildTasks = new List<Func<string>>(); public Builder BuildAddressClause(Address address) { // 捕获参数副本避免闭包问题 var addressCopy = address; // 将原有构建逻辑封装为委托存入任务列表,不立即执行 _buildTasks.Add(() => { // 此处替换为你原本的Address条件生成逻辑 if (addressCopy == null) return string.Empty; return $"address = N'{addressCopy.Detail.Replace("'", "''")}'"; }); return this; } public Builder BuildBankAccountClause(BankAccountInformation bankInfo) { var bankInfoCopy = bankInfo; _buildTasks.Add(() => { // 此处替换为你原本的银行账户条件生成逻辑 if (bankInfoCopy == null) return string.Empty; return $"bank_account = '{bankInfoCopy.AccountNo.Replace("'", "''")}'"; }); return this; } public Builder BuildAClause(Something param) { var paramCopy = param; _buildTasks.Add(() => { // 此处替换为你原本的A条件生成逻辑 if (paramCopy == null) return string.Empty; return $"a_column = '{paramCopy.Value}'"; }); return this; } public Builder BuildBClause(Something param) { var paramCopy = param; _buildTasks.Add(() => { // 此处替换为你原本的B条件生成逻辑 if (paramCopy == null) return string.Empty; return $"b_column = '{paramCopy.Value}'"; }); return this; } public PersonQueryBuilder Build() { // 并发启动所有构建任务 var runTasks = _buildTasks.Select(task => Task<string>.Factory.StartNew(task)).ToArray(); // 等待所有任务执行完成 Task.WaitAll(runTasks); // 收集所有非空的有效SQL片段 var validClauses = runTasks.Select(t => t.Result).Where(c => !string.IsNullOrWhiteSpace(c)).ToList(); return new PersonQueryBuilder(validClauses); } } }
使用方式
改造后原有调用逻辑完全不需要改动,和之前保持一致:
PersonQueryBuilder person = new PersonQueryBuilder.Builder() .BuildAddressClause(request.PersonInformation.Address) .BuildBankAccountClause(request.PersonInformation.BankAccountInformation) .BuildAClause(request.Something) .BuildBClause(request.Something) .Build();
注意事项
- 若单个构建逻辑耗时极短,并发带来的线程调度开销可能高于串行执行,建议改造后做性能测试确认收益
- 若需要调整并发数、调度策略,可以给
Task.Factory.StartNew传入自定义的TaskScheduler参数 - 避免在构建逻辑中修改全局共享变量,若必须使用要做好线程安全处理
内容的提问来源于stack exchange,提问作者Prateek
相关产品推荐
相关产品推荐

