Dapper GetList与Query方法性能差异及GetList全表扫描问题咨询
DapperExtensions GetList() 全表扫描问题分析与优化方案
为什么会出现全表读取的性能问题?
问题核心出在你对DapperExtensions的GetList<T>方法的使用逻辑上:
- 你的
GetAll<T>方法里调用了conn.GetList<T>(null, null, trans),这里第一个参数是查询条件,当它为null时,DapperExtensions会生成不带WHERE子句的SQL,也就是直接执行SELECT * FROM vwWfActivityInstanceTasks,自然会全量读取视图数据。 - 后续的LINQ查询是在内存中对全量数据做过滤,等于先把整个视图的所有数据拉到应用内存,再筛选符合条件的记录,这就导致了严重的性能损耗。
如何优化?(同时保持多数据库兼容性)
DapperExtensions本身就支持跨数据库的条件查询,核心是要正确传入查询条件,让过滤逻辑在数据库层面完成,而不是在内存里处理。
1. 重构扩展方法,支持传入查询条件
先修改你的Dapper扩展方法,让它能接收条件参数:
// 基础版:支持匿名对象传简单条件 public IEnumerable<T> GetList<T>(IDbConnection conn, IDbTransaction trans, object filterConditions) where T : class { // 传入条件后,DapperExtensions会自动生成对应的WHERE子句 var dataList = conn.GetList<T>(filterConditions, transaction: trans); return dataList; } // 进阶版:支持复杂条件组合(比如AND/OR嵌套) public IEnumerable<T> GetListWithComplexFilter<T>(IDbConnection conn, IDbTransaction trans, IPredicate predicate) where T : class { var dataList = conn.GetList<T>(predicate, transaction: trans); return dataList; }
2. 业务代码中正确调用,实现精准查询
针对你的场景,用匿名对象传条件最简单,效果和你原生SQL完全一致,还能自动适配不同数据库的语法:
// 直接传入过滤条件,DapperExtensions会生成带WHERE的精准SQL var list = Repository.GetList<TaskViewEntity>(conn, trans, new { ActivityInstanceID = activityInstanceID, ProcessInstanceID = processInstanceID }).ToList();
如果以后需要更复杂的条件(比如范围查询、OR逻辑),可以用PredicateGroup构建强类型条件:
var filterGroup = new PredicateGroup { Operator = GroupOperator.And, Predicates = new List<IPredicate> { Predicates.Field<TaskViewEntity>(f => f.ActivityInstanceID, Operator.Eq, activityInstanceID), Predicates.Field<TaskViewEntity>(f => f.ProcessInstanceID, Operator.Eq, processInstanceID) } }; var list = Repository.GetListWithComplexFilter<TaskViewEntity>(conn, trans, filterGroup).ToList();
3. 额外性能提升建议
- 给视图加合适的索引:如果视图底层的表在
ActivityInstanceID和ProcessInstanceID上没有索引,建议添加联合索引,这能大幅加快数据库层面的过滤速度。 - **避免SELECT ***:明确指定需要返回的字段,减少数据传输量,DapperExtensions支持指定返回字段:
var requiredColumns = new List<string> { "ActivityInstanceID", "ProcessInstanceID", "TaskTitle", "Assignee" }; var list = conn.GetList<TaskViewEntity>(filterConditions, columns: requiredColumns, transaction: trans).ToList();
内容的提问来源于stack exchange,提问作者Bes Ley
相关产品推荐
相关产品推荐

