项目介绍
high performance lightweight solution for efcore sharding table and sharding database support read-write-separation .一款ef-core下高性能、轻量级针对分表分库读写分离的解决方案,具有零依赖、零学习成本、零业务代码入侵
项目详情
English | 中文
ShardingCore
一款ef-core下高性能、轻量级针对分表分库读写分离的解决方案。
- 零依赖
- 零学习成本
- 零业务代码入侵
特别用户

全项目基于.Net专业团队自研,源头工厂,价格约是官方的二十分之一不到,获得全网数万用户好评,稳定安全,快速可靠!
- ①支持 编程/对话/视频/图片/翻译/知识库/插件 直接使用 等等。
- ②支持全球顶流模型,支持最强编程ClaudeCode/Codex/GeminiCli。
- ③支持一个key通用claude、gpt、gemini等全站模型。
- ④包售后,充值后提供1对1售后服务,手把手教玩ai 。
用Ai就选择意心Ai,省心放心爽用!让你不再有Ai焦虑!


社区合作伙伴和赞助商

📚 Documentation
如何选择版本
- shardingcore 最新版本.efcore版本.x.x
- 版本号第一位是shardingcore的版本号使用最大的即可
- 版本号第二位是efcore版本号使用对应的版本号即可
- 最后两位版本号使用最大即可
- efcore10使用shardingcore7.10.x.x,
- efcore9使用shardingcore7.9.x.x,
- efcore8使用shardingcore7.8.x.x,
- efcore7使用shardingcore7.7.x.x,
- efcore6使用shardingcore7.6.x.x,
- efcore5使用shardingcore7.5.x.x,
- efcore3使用shardingcore7.3.x.x,
- efcore2使用shardingcore7.2.x.x
Abp.VNext、WTM、FURION 框架集成
- ShardingFrameWork demos
依赖
ShardingCore 6.7.0.0之前版本
版本号:a.b.c.d其中,a表示efcore版本号
| Release | EF Core | .NET | .NET (Core) |
|---|---|---|---|
| 6.x.x.x | 6.0.0 | net 6.0 | 6.0+ |
| 5.x.x.x | 5.0.10 | Standard 2.1 | 5.0+ |
| 3.x.x.x | 3.1.18 | Standard 2.0 | 2.0+ |
| 2.x.x.x | 2.2.6 | Standard 2.0 | 2.0+ |
ShardingCore 6.7.0.0之后
版本号:a.b.c.d其中已无相关efcore选择,使用条件编译绑定.net平台,6.7.0.0之后如果您是netcoreapp2那么直接使用efcore2,如果是netcoreapp3那么直接使用efcore3如果是net5就直接用efcore6依次类推
| Release | EF Core | .NET (Core) |
|---|---|---|
| 6.7.0.0+ | 6.x | net6 |
| 6.7.0.0+ | 5.x | net5 or netstandard2.1 |
| 6.7.0.0+ | 3.x | netcoreapp3 or netstandard2.0 |
| 6.7.0.0+ | 2.x | netcoreapp2 |
快速开始
5步实现按月分表,且支持自动化建表建库
第一步安装依赖
选择您的efcore的数据库驱动版本
# 请对应安装您需要的版本
PM> Install-Package ShardingCore
# use sqlserver
PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer
# use mysql
#PM> Install-Package Pomelo.EntityFrameworkCore.MySql
# use other database driver,if efcore support第二步创建查询对象
查询对象
///
/// order table
///
public class Order
{
///
/// order Id
///
public string Id { get; set; }
///
/// payer id
///
public string Payer { get; set; }
///
/// pay money cent
///
public long Money { get; set; }
///
/// area
///
public string Area { get; set; }
///
/// order status
///
public OrderStatusEnum OrderStatus { get; set; }
///
/// CreationTime
///
public DateTime CreationTime { get; set; }
}
public enum OrderStatusEnum
{
NoPay=1,
Paying=2,
Payed=3,
PayFail=4
}第三步创建dbcontext
dbcontext AbstractShardingDbContext和IShardingTableDbContext如果你是普通的DbContext那么就继承AbstractShardingDbContext需要分表就实现IShardingTableDbContext,如果只有分库可以不实现IShardingTableDbContext接口
public class MyDbContext:AbstractShardingDbContext,IShardingTableDbContext
{
public MyDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity(entity =>
{
entity.HasKey(o => o.Id);
entity.Property(o => o.Id).IsRequired().IsUnicode(false).HasMaxLength(50);
entity.Property(o=>o.Payer).IsRequired().IsUnicode(false).HasMaxLength(50);
entity.Property(o => o.Area).IsRequired().IsUnicode(false).HasMaxLength(50);
entity.Property(o => o.OrderStatus).HasConversion();
entity.ToTable(nameof(Order));
});
}
///
/// empty impl if use sharding table
///
public IRouteTail RouteTail { get; set; }
}第四步添加分表路由
路由构造函数支持依赖注入,依赖注入的对象生命周期必须是单例
public class OrderVirtualTableRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute
{
///
/// fixed value don't use DateTime.Now because if if application restart this value where change
///
///
public override DateTime GetBeginTime()
{
return new DateTime(2021, 1, 1);
}
///
/// configure sharding property
///
///
public override void Configure(EntityMetadataTableBuilder builder)
{
builder.ShardingProperty(o => o.CreationTime);
}
///
/// enable auto create table job
///
///
public override bool AutoCreateTableByTime()
{
return true;
}
}第五步配置启动项
无论你是何种数据库只需要修改AddDefaultDataSource里面的链接字符串 请不要修改委托内部的UseXXX参数 conStr and connection
public void ConfigureServices(IServiceCollection services)
{
//额外添加分片配置
services.AddShardingDbContext()
.UseRouteConfig(op =>
{
op.AddShardingTableRoute();
}).UseConfig(op =>
{
op.UseShardingQuery((connStr, builder) =>
{
//connStr is delegate input param
builder.UseSqlServer(connStr);
});
op.UseShardingTransaction((connection, builder) =>
{
//connection is delegate input param
builder.UseSqlServer(connection);
});
//use your data base connection string
op.AddDefaultDataSource(Guid.NewGuid().ToString("n"),
"Data Source=localhost;Initial Catalog=EFCoreShardingTableDB;Integrated Security=True;");
}).AddShardingCore();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//not required, enable check table missing and auto create,非必须 启动检查缺少的表并且创建
app.ApplicationServices.UseAutoTryCompensateTable();
// other configure....
}这样所有的配置就完成了你可以愉快地对Order表进行按月分表了
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly MyDbContext _myDbContext;
public ValuesController(MyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
[HttpGet]
public async Task Get()
{
var order = await _myDbContext.Set().FirstOrDefaultAsync(o => o.Id == "2");
return OK(order)
}
}性能
Test
- on expression compile cache
- ShardingCore x.3.1.63+ version
- efcore 6.0 version
- order id is string, sharding mod(hashcode%5)
- N mean execute count
性能损耗 sql server 2012,data rows 7734363 =773w
// Summary
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.18363.1500 (1909/November2019Update/19H2)
AMD Ryzen 9 3900X, 1 CPU, 24 logical and 12 physical cores
.NET SDK=6.0.100
[Host] : .NET 6.0.0 (6.0.21.52210), X64 RyuJIT
DefaultJob : .NET 6.0.0 (6.0.21.52210), X64 RyuJIT
| Method | N | Mean | Error | StdDev |
|---|---|---|---|---|
| NoShardingIndexFirstOrDefaultAsync | 10 | 1.512 ms | 0.0071 ms | 0.0063 ms |
| ShardingIndexFirstOrDefaultAsync | 10 | 1.567 ms | 0.0127 ms | 0.0113 ms |
针对未分片数据的查询性能,可以看出10次查询差距为0.05ms,单次查询损耗约为5微妙=0.005毫秒,损耗占比为3%,
结论:efcore 原生查询和sharding-core的查询在针对未分片对象查询上性能可达原先的97%具有极高的性能
性能测试
sql server 2012,data rows 7734363 =773w
// Summary
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.18363.1500 (1909/November2019Update/19H2)
AMD Ryzen 9 3900X, 1 CPU, 24 logical and 12 physical cores
.NET SDK=6.0.101
[Host] : .NET 6.0.1 (6.0.121.56705), X64 RyuJIT
DefaultJob : .NET 6.0.1 (6.0.121.56705), X64 RyuJIT
| Method | N | Mean | Error | StdDev |
|---|---|---|---|---|
| NoShardingIndexFirstOrDefaultAsync | 10 | 1.678 ms | 0.0323 ms | 0.0359 ms |
| ShardingIndexFirstOrDefaultAsync | 10 | 2.005 ms | 0.0161 ms | 0.0143 ms |
| NoShardingNoIndexFirstOrDefaultAsync | 10 | 495.933 ms | 9.4911 ms | 10.5494 ms |
| ShardingNoIndexFirstOrDefaultAsync | 10 | 596.112 ms | 11.8907 ms | 13.2165 ms |
| NoShardingNoIndexCountAsync | 10 | 477.537 ms | 1.4817 ms | 1.2373 ms |
| ShardingNoIndexCountAsync | 10 | 594.833 ms | 7.4057 ms | 5.7819 ms |
| NoShardingNoIndexLikeToListAsync | 10 | 665.277 ms | 1.3382 ms | 1.1174 ms |
| ShardingNoIndexLikeToListAsync | 10 | 840.865 ms | 16.1917 ms | 17.3249 ms |
| NoShardingNoIndexToListAsync | 10 | 480.368 ms | 1.3688 ms | 1.2134 ms |
| ShardingNoIndexToListAsync | 10 | 604.850 ms | 8.6204 ms | 8.0635 ms |
mysql 5.7,data rows 7553790=755w innerdb_buffer_size=3G
// Summary
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.18363.1500 (1909/November2019Update/19H2)
AMD Ryzen 9 3900X, 1 CPU, 24 logical and 12 physical cores
.NET SDK=6.0.101
[Host] : .NET 6.0.1 (6.0.121.56705), X64 RyuJIT
DefaultJob : .NET 6.0.1 (6.0.121.56705), X64 RyuJIT
| Method | N | Mean | Error | StdDev |
|---|---|---|---|---|
| NoShardingIndexFirstOrDefaultAsync | 10 | 5.646 ms | 0.0164 ms | 0.0145 ms |
| ShardingIndexFirstOrDefaultAsync | 10 | 5.679 ms | 0.0359 ms | 0.0319 ms |
| NoShardingNoIndexFirstOrDefaultAsync | 10 | 5,212.736 ms | 230.0841 ms | 678.4080 ms |
| ShardingNoIndexFirstOrDefaultAsync | 10 | 2,013.107 ms | 10.4256 ms | 9.2420 ms |
| NoShardingNoIndexCountAsync | 10 | 9,483.988 ms | 42.0931 ms | 39.3739 ms |
| ShardingNoIndexCountAsync | 10 | 2,029.698 ms | 12.4008 ms | 10.9929 ms |
| NoShardingNoIndexLikeToListAsync | 10 | 10,569.283 ms | 20.9163 ms | 16.3301 ms |
| ShardingNoIndexLikeToListAsync | 10 | 2,208.804 ms | 11.0483 ms | 10.3346 ms |
| NoShardingNoIndexToListAsync | 10 | 9,485.263 ms | 21.2558 ms | 17.7496 ms |
| ShardingNoIndexToListAsync | 10 | 2,012.086 ms | 39.2986 ms | 45.2563 ms |
具体可以通过first前两次结果来计算得出结论单次查询的的损耗为0.04毫秒上下, sqlserver的各项数据在分表和未分表的情况下都几乎差不多可以得出在770w数据集情况下数据库还并未是数据瓶颈的关键,但是mysql可以看到在分表和未分表的情况下如果涉及到没有索引的全表扫描那么性能的差距将是分表后的表数目之多,测试中为5-6倍,也就是分表数目
使用介绍
以下所有例子都以Sql Server为例 展示的代码均是分表为例,如果需要分库可以参考Sample.SqlServerShardingDataSource 其他数据库亦是如此
简介
简单介绍下这个库,这个库的所有版本都是由对应的efcore版本号为主的版本,第二个版本号如果是2的表示仅支持分库,如果是3+的表示支持分库分表,这个库目前分成两个主要版本一个是main分支一个是shardingTableOnly分支,该库支持分库完全自定义路由适用于95%的业务需求,分表支持x+y+z,x表示固定的表名,y表示固定的表名和表后缀之间的联系(可以为空),z表示表后缀,可以按照你自己的任意业务逻辑进行切分,
如:user_0,user_1或者user202101,user202102...当然该库同样适用于多租户模式下的隔离
支持多种查询包括join,group by,max,count,min,avg,sum ...等一系列查询,之后可能会添加更多支持,目前该库的使用非常简单,基本上就是针对IQueryable的扩展,为了保证
该库的干净零依赖,如果需要实现自动建表需要自己配合定时任务,即可完成24小时无人看管自动管理。该库提供了 IShardingTableCreator
作为建表的依赖,如果需要可以参考 按天自动建表 该demo是针对分库的动态添加
概念
本库的几个简单的核心概念:
分库概念
- [DataSourceName]
数据源名称用来将对象路由到具体的数据源 - [IVirtualDataSource]
虚拟数据源 IVirtualDataSource [IVirtualDataSourceRoute]
分库路由 IVirtualDataSourceRoute分表概念
- [Tail]
尾巴、后缀物理表的后缀 - [TailPrefix]
尾巴前缀虚拟表和物理表的后缀中间的字符 - [物理表]
顾名思义就是数据库对应的实际表信息,表名(tablename+ tailprefix+ tail) IPhysicTable - [虚拟表]
虚拟表就是系统将所有的物理表在系统里面进行抽象的一个总表对应到程序就是一个entityIVirtualTable - [虚拟路由]
虚拟路由就是联系虚拟表和物理表的中间介质,虚拟表在整个程序中只有一份,那么程序如何知道要查询系统哪一张表呢,最简单的方式就是通过虚拟表对应的路由IVirtualTableRoute
,由于基本上所有的路由都是和业务逻辑相关的所以虚拟路由由用户自己实现,该框架提供一个高级抽象
优点
- [支持自定义分库]
- [支持读写分离]
- [支持高性能分页]
- [支持手动路由]
- [支持批量操作]
- [支持自定义分表规则]
- [支持任意类型分表key]
- [对dbcontext学习成本0]
- [支持分表下的连表]
join,group by,max,count,min,avg,sum - [支持针对批处理的使用] EFCore.BulkExtensions ...支持efcore的扩展生态
- [提供多种默认分表规则路由] 按时间,按取模 可自定义
- [针对分页进行优化] 大页数跳转支持低内存流式处理,高性能分页
缺点
- [消耗连接]出现分表与分表对象进行join如果条件没法索引到具体表会生成
笛卡尔积导致连接数爆炸,后期会进行针对该情况的配置
安装
or
or
开始
分表
我们以用户取模来做例子,配置entity 推荐 fluent api
public class SysUserMod
{
///
/// 用户Id用于分表
///
public string Id { get; set; }
///
/// 用户名称
///
public string Name { get; set; }
///
/// 用户姓名
///
public int Age { get; set; }
}
创建virtual route
实现 AbstractShardingOperatorVirtualTableRoute
抽象,或者实现系统默认的虚拟路由
框架默认有提供几个简单的路由 默认路由
public class SysUserModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualRoute
{
//2 tail length:00,01,02......99
//3 hashcode % 3: [0,1,2]
public SysUserModVirtualTableRoute() : base(2,3)
{
}
public override void Configure(EntityMetadataTableBuilder builder)
{
builder.ShardingProperty(o => o.Id);
}
}如果你使用分表必须创建一个继承自IShardingTableDbContext接口的DbContext,
必须实现IShardingDbContext,默认提供了AbstractShardingDbContext
//DefaultTableDbContext is acutal execute dbcontext
public class DefaultShardingDbContext:AbstractShardingDbContext,IShardingTableDbContext
{
public DefaultShardingDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new SysUserModMap());
}
public IRouteTail RouteTail { get; set; }
}Startup.cs 下的 ConfigureServices(IServiceCollection services)
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
//if u want use no sharding operate
//services.AddDbContext(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDB;Integrated Security=True"));
//add shardingdbcontext support life scope
services.AddShardingDbContext(
(conStr, builder) => builder.UseSqlServer(conStr)
)
.Begin(o =>
{
o.CreateShardingTableO
...(内容过长,已截断,更多详情请访问项目地址)
## ⬇️ 下载地址 ##
{cloud title="sharding-core 源码下载" type="gitee" url="https://gitee.com/xuejm/sharding-core/repository/archive/main.zip" /}