SqlSugar批量查询

在实际业务系统中,批量查询是最高频的数据库操作。SqlSugar提供了丰富而强大的批量查询功能,能够显著提升数据检索效率。本文将全面解析SqlSugar的批量查询技术。

1. 基础批量查询方法

1.1 主键列表批量查询

// 根据主键列表批量查询
var ids = new List<long> { 1, 2, 3, 4, 5 };
var list = db.Queryable<Order>().In(ids).ToList();

// 异步版本
var list = await db.Queryable<Order>().In(ids).ToListAsync();

// 只查询特定字段
var result = await db.Queryable<Order>()
    .Where(o => ids.Contains(o.Id))
    .Select(o => new { o.Id, o.OrderNo, o.Amount })
    .ToListAsync();

1.2 条件批量查询

// 多条件批量查询
var result = db.Queryable<Order>()
    .Where(o => o.Status == OrderStatus.Completed)
    .Where(o => o.CreateTime >= DateTime.Now.AddDays(-7))
    .WhereIF(!string.IsNullOrEmpty(keyword), o => o.OrderNo.Contains(keyword))
    .ToList();

// 复杂条件组合
var query = db.Queryable<Order>();
if (statusList != null && statusList.Any())
    query = query.Where(o => statusList.Contains(o.Status));
if (minAmount.HasValue)
    query = query.Where(o => o.Amount >= minAmount.Value);

var result = query.ToList();

2. 高性能批量查询方案

2.1 分页批量查询(大数据量推荐)

public async Task<PageResult<T>> BatchQueryInPages<T>(
    Expression<Func<T, bool>> whereExpression,
    int pageSize = 1000,
    string orderBy = "Id") where T : class, new()
{
    var result = new PageResult<T> { Data = new List<T>() };
    var hasMoreData = true;
    var pageIndex = 1;

    while (hasMoreData)
    {
        try
        {
            var pageData = await db.Queryable<T>()
                .Where(whereExpression)
                .OrderBy(orderBy)
                .ToPageListAsync(pageIndex, pageSize);

            if (pageData == null || !pageData.Any())
            {
                hasMoreData = false;
                break;
            }

            result.Data.AddRange(pageData);
            result.TotalCount += pageData.Count;

            // 如果返回数据少于页大小,说明没有更多数据
            if (pageData.Count < pageSize)
            {
                hasMoreData = false;
            }

            pageIndex++;
            Console.WriteLine($"已加载 {result.TotalCount} 条记录...");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"第{pageIndex}页查询失败: {ex.Message}");
            break;
        }
    }

    return result;
}

// 使用示例
var result = await BatchQueryInPages<Order>(
    o => o.CreateTime >= DateTime.Now.AddMonths(-1), 
    2000, "CreateTime DESC");

2.2 并行批量查询

public async Task<List<T>> ParallelBatchQuery<T>(
    List<Expression<Func<T, bool>>> conditions) where T : class, new()
{
    var tasks = conditions.Select(condition =>
        db.Queryable<T>().Where(condition).ToListAsync()
    ).ToArray();

    var results = await Task.WhenAll(tasks);
    return results.SelectMany(x => x).ToList();
}

// 分片并行查询
public async Task<List<T>> ShardedParallelQuery<T>(
    Expression<Func<T, bool>> baseCondition,
    string shardColumn,
    int shardCount) where T : class, new()
{
    var tasks = new List<Task<List<T>>>();

    for (int i = 0; i < shardCount; i++)
    {
        int currentShard = i;
        var task = Task.Run(async () =>
        {
            return await db.Queryable<T>()
                .Where(baseCondition)
                .Where($"{shardColumn} % {shardCount} = {currentShard}")
                .ToListAsync();
        });
        tasks.Add(task);
    }

    var results = await Task.WhenAll(tasks);
    return results.SelectMany(x => x).ToList();
}

3. 高级批量查询技巧

3.1 多表关联批量查询

// 链式多表查询
var result = await db.Queryable<Order>()
    .LeftJoin<User>((o, u) => o.UserId == u.Id)
    .LeftJoin<OrderDetail>((o, u, od) => o.Id == od.OrderId)
    .Where((o, u, od) => o.Status == OrderStatus.Completed && u.VipLevel > 1)
    .Select((o, u, od) => new OrderDto
    {
        OrderId = o.Id,
        OrderNo = o.OrderNo,
        UserName = u.Name,
        TotalAmount = o.Amount,
        ItemCount = SqlFunc.AggregateSum(od.Quantity)
    })
    .GroupBy((o, u, od) => new { o.Id, o.OrderNo, u.Name })
    .ToListAsync();

// 使用Includes进行关联加载
var orders = await db.Queryable<Order>()
    .Includes(o => o.User)  // 加载用户信息
    .Includes(o => o.OrderDetails)  // 加载订单详情
    .Includes(o => o.OrderDetails.First().Product)  // 加载商品信息
    .Where(o => o.CreateTime >= DateTime.Now.AddDays(-7))
    .ToListAsync();

3.2 动态条件批量查询

public async Task<List<Order>> DynamicBatchQuery(OrderQueryDto query)
{
    var exp = Expressionable.Create<Order>();
    
    // 动态构建条件
    if (!string.IsNullOrEmpty(query.OrderNo))
        exp.And(o => o.OrderNo.Contains(query.OrderNo));
        
    if (query.Status.HasValue)
        exp.And(o => o.Status == query.Status.Value);
        
    if (query.StartTime.HasValue)
        exp.And(o => o.CreateTime >= query.StartTime.Value);
        
    if (query.EndTime.HasValue)
        exp.And(o => o.CreateTime <= query.EndTime.Value);
        
    if (query.MinAmount.HasValue)
        exp.And(o => o.Amount >= query.MinAmount.Value);
        
    if (query.MaxAmount.HasValue)
        exp.And(o => o.Amount <= query.MaxAmount.Value);

    var sqlQuery = db.Queryable<Order>().Where(exp.ToExpression());

    // 动态排序
    if (!string.IsNullOrEmpty(query.SortField))
    {
        var sortOrder = query.SortOrder?.ToLower() == "desc" ? " DESC" : " ASC";
        sqlQuery = sqlQuery.OrderBy($"{query.SortField}{sortOrder}");
    }
    else
    {
        sqlQuery = sqlQuery.OrderBy("Id DESC");
    }

    // 分页
    if (query.PageSize > 0)
    {
        sqlQuery = sqlQuery.ToPageList(query.PageIndex, query.PageSize);
    }

    return await sqlQuery.ToListAsync();
}

4. 性能优化策略

4.1 查询字段优化

public class QueryOptimizationHelper
{
    // 只查询需要的字段
    public async Task<List<OrderSimpleDto>> OptimizedQuery()
    {
        return await db.Queryable<Order>()
            .Where(o => o.CreateTime >= DateTime.Now.AddMonths(-1))
            .Select(o => new OrderSimpleDto
            {
                Id = o.Id,
                OrderNo = o.OrderNo,
                Amount = o.Amount,
                Status = o.Status
            })
            .ToListAsync();
    }

    // 使用NoTracking提高查询性能
    public async Task<List<Order>> NoTrackingQuery()
    {
        return await db.Queryable<Order>()
            .With(SqlWith.NoLock)  // SQL Server的NOLOCK
            .ASNoTracking()  // 不跟踪实体状态
            .Where(o => o.Status == OrderStatus.Completed)
            .ToListAsync();
    }

    // 批量查询使用索引优化
    public async Task<List<Order>> IndexOptimizedQuery(List<long> ids)
    {
        // 分批查询避免IN条件过长
        var batchSize = 1000;
        var result = new List<Order>();
        
        for (int i = 0; i < ids.Count; i += batchSize)
        {
            var batchIds = ids.Skip(i).Take(batchSize).ToList();
            var batchResult = await db.Queryable<Order>()
                .Where(o => batchIds.Contains(o.Id))
                .ToListAsync();
            result.AddRange(batchResult);
        }
        
        return result;
    }
}

SqlSugar批量查询的最佳实践建议:

  1. 小数据量(万条以内):使用直接IN查询或条件查询

  2. 中等数据量(万条到十万条):使用分页查询

  3. 大数据量(十万条以上):必须使用分页查询,考虑并行处理

  4. 复杂关联查询:使用Includes或Join进行关联加载

  5. 高频查询:结合缓存策略提升性能

关键优化技巧:

  • 字段优化:只查询需要的字段,避免SELECT *

  • 索引利用:确保查询条件使用合适的索引

  • 分页策略:大数据量使用Keyset分页替代OFFSET分页

  • 缓存应用:合理使用查询缓存减少数据库压力

  • 监控告警:添加查询性能监控和慢查询告警

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code_shenbing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值