导读:本期聚焦于小伙伴创作的《C#如何实现分表分库?C#使用ShardingCore处理超大数据量存储的方案是什么》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#如何实现分表分库?C#使用ShardingCore处理超大数据量存储的方案是什么》有用,将其分享出去将是对创作者最好的鼓励。

当业务系统的数据量突破千万甚至亿级级别时,单表的查询和写入性能会明显下降,索引维护成本也会大幅增加,此时分表分库是常用的优化方案。分表是将一张大表按照规则拆分成多张结构相同的子表,分库是将拆分后的表分布到不同的数据库实例中,以此降低单节点的存储和访问压力。

C#如何实现分表分库?C#使用ShardingCore处理超大数据量存储的方案是什么

ShardingCore框架简介

ShardingCore是一款针对C#生态的开源分表分库框架,它基于EF Core实现,支持按照时间、哈希、范围等多种规则进行分表分库,同时兼容大部分EF Core的原有用法,开发者不需要大幅修改现有代码就能接入分表分库能力,降低了迁移成本。

环境准备与依赖安装

首先需要在C#项目中安装ShardingCore相关的NuGet包,这里以.NET 6项目为例,需要安装以下两个核心包:

  • ShardingCore
  • ShardingCore.Core

如果使用SQL Server数据库,还需要安装对应的EF Core数据库驱动:

  • Microsoft.EntityFrameworkCore.SqlServer

定义分片规则

分片规则是分表分库的核心,我们需要先定义实体类,再配置对应的分片逻辑。假设我们有一个订单表,按照订单创建时间按月分表。

1. 定义订单实体类

首先创建订单实体,包含订单的基本字段:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ShardingDemo.Entities
{
    [Table("Order")]
    public class Order
    {
        [Key]
        public string Id { get; set; }

        public string OrderNo { get; set; }

        public decimal Amount { get; set; }

        public DateTime CreateTime { get; set; }
    }
}

2. 配置分表规则

接下来创建分表规则配置类,指定按照CreateTime字段按月分表:

using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using ShardingCore.Helpers;
using ShardingDemo.Entities;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ShardingDemo.ShardingConfig
{
    public class OrderVirtualTableRoute : AbstractShardingTimeKeyDateTimeVirtualTableRoute<Order>
    {
        // 指定分表的时间字段
        public override string ShardingKeyToTail(DateTime time)
        {
            return time.ToString("yyyyMM");
        }

        // 获取分片键的值
        public override Func<string, bool> GetRouteToFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator)
        {
            return base.GetRouteToFilter(shardingKey, shardingOperator);
        }

        // 配置分表的后缀格式,这里按月分表,后缀为yyyyMM
        protected override string TimeFormatToTail(DateTime time)
        {
            return time.ToString("yyyyMM");
        }

        // 获取所有分表的后缀,这里示例返回最近3个月的分表后缀
        public override List<string> GetAllTails()
        {
            var result = new List<string>();
            var now = DateTime.Now;
            for (int i = 0; i < 3; i++)
            {
                result.Add(now.AddMonths(-i).ToString("yyyyMM"));
            }
            return result;
        }
    }
}

配置DbContext与ShardingCore

接下来需要配置EF Core的DbContext,同时集成ShardingCore的分片能力。

1. 创建分片DbContext

using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.DbContextInfos;
using ShardingCore.Extensions;
using ShardingDemo.Entities;
using System;
using System.Linq;

namespace ShardingDemo.Data
{
    public class ShardingDbContext : DbContext
    {
        public DbSet<Order> Orders { get; set; }

        public ShardingDbContext(DbContextOptions<ShardingDbContext> options) : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Order>(entity =>
            {
                entity.HasKey(e => e.Id);
                entity.Property(e => e.OrderNo).HasMaxLength(50);
            });
        }

        // 重写SaveChanges方法,支持分片写入
        public override int SaveChanges()
        {
            return this.SaveChangesSharding();
        }

        public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
        {
            return this.SaveChangesShardingAsync(cancellationToken);
        }
    }
}

2. 注册ShardingCore服务

在Program.cs中注册ShardingCore相关服务,配置数据库连接和分片规则:

using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Extensions;
using ShardingDemo.Data;
using ShardingDemo.ShardingConfig;

var builder = WebApplication.CreateBuilder(args);

// 注册ShardingCore服务
builder.Services.AddShardingDbContext<ShardingDbContext>(
    (conStr, builder) =>
    {
        builder.UseSqlServer(conStr);
    },
    opt =>
    {
        opt.UseShardingOptions(new ShardingOptions()
            .AddShardingTableRoute<OrderVirtualTableRoute>());
    },
    builder.Configuration.GetConnectionString("DefaultConnection")
);

var app = builder.Build();

// 初始化ShardingCore,确保分表路由生效
app.Services.UseShardingCore();

app.MapGet("/", () => "ShardingCore Demo Running");

app.Run();

这里需要在appsettings.json中配置数据库连接字符串,示例配置如下:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=127.0.0.1;Database=ShardingDemo;User Id=sa;Password=your_password;"
  }
}

分表数据操作示例

配置完成后,就可以像使用普通EF Core一样操作分表数据,ShardingCore会自动根据分片规则路由到对应的表。

1. 插入分表数据

using Microsoft.AspNetCore.Mvc;
using ShardingDemo.Data;
using ShardingDemo.Entities;
using System;
using System.Threading.Tasks;

namespace ShardingDemo.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class OrderController : ControllerBase
    {
        private readonly ShardingDbContext _dbContext;

        public OrderController(ShardingDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        [HttpPost("add")]
        public async Task<IActionResult> AddOrder()
        {
            var order = new Order
            {
                Id = Guid.NewGuid().ToString(),
                OrderNo = "ORD" + DateTime.Now.ToString("yyyyMMddHHmmss"),
                Amount = 100.5m,
                CreateTime = DateTime.Now
            };
            _dbContext.Orders.Add(order);
            await _dbContext.SaveChangesAsync();
            return Ok("订单添加成功");
        }
    }
}

插入数据时,ShardingCore会根据CreateTime的值自动计算分表后缀,将数据写入对应的月份订单表中,如果对应的分表不存在,框架会自动创建。

2. 查询分表数据

查询时如果带了分片键条件,ShardingCore会自动路由到对应的分表,提升查询效率:

[HttpGet("list")]
public async Task<IActionResult> GetOrderList()
{
    // 查询当月创建的订单,会自动路由到对应月份的分表
    var orders = await _dbContext.Orders
        .Where(o => o.CreateTime >= DateTime.Now.Date && o.CreateTime < DateTime.Now.AddDays(1))
        .ToListAsync();
    return Ok(orders);
}

如果没有带分片键条件,ShardingCore会查询所有分表的数据并合并结果,不过这种全表扫描的性能会低于带分片条件的查询,实际使用中尽量带上分片键条件。

分库配置说明

如果需要分库,只需要在ShardingCore的配置中添加多数据库配置即可,比如按照订单Id的哈希值分配到不同的数据库实例:

// 分库路由配置示例,按照订单Id哈希分库
public class OrderVirtualDataSourceRoute : AbstractShardingKeyStringVirtualDataSourceRoute<Order>
{
    private readonly List<string> _dataSourceNames = new List<string> { "db0", "db1", "db2" };

    public override string ShardingKeyToDataSourceName(string shardingKey)
    {
        // 简单哈希取模分配数据库
        var hash = Math.Abs(shardingKey.GetHashCode()) % _dataSourceNames.Count;
        return _dataSourceNames[hash];
    }

    public override List<string> GetAllDataSourceNames()
    {
        return _dataSourceNames;
    }

    public override Func<string, bool> GetRouteToFilter(string shardingKey, ShardingOperatorEnum shardingOperator)
    {
        return base.GetRouteToFilter(shardingKey, shardingOperator);
    }
}

然后在服务注册时同时添加分表路由和分库路由即可实现分表分库组合使用。

注意事项

  • 分片键的选择非常重要,尽量选择查询频率高、区分度高的字段作为分片键,避免后续查询出现全分片扫描的情况。
  • 分表后如果需要跨分表做聚合查询,性能会比单表差,尽量在业务层面避免复杂的跨分片聚合操作。
  • ShardingCore支持分表的自动创建和迁移,但是生产环境建议提前做好分表的规划,避免频繁创建分表带来的性能波动。
  • 如果使用的是其他数据库比如MySQL、PostgreSQL,只需要替换对应的EF Core数据库驱动,配置方式基本一致。

C#ShardingCore分表分库超大数据量存储修改时间:2026-07-10 01:48:41

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。