重要

2021-11-4 重要 大约 5 分钟

警告

!!!升级如果不使用app.ApplictaionServices.UseAutoShardingCreate()将不会自动创建表任务请注意,如果您是IIS代理那么请关闭应用程序池的固定回收和空闲回收设置为0,不然ShardingCore的创建表的任务可能不会生效

!!!升级如果不使用app.ApplictaionServices.UseAutoShardingCreate()将不会自动创建表任务请注意,如果您是IIS代理那么请关闭应用程序池的固定回收和空闲回收设置为0,不然ShardingCore的创建表的任务可能不会生效

!!!升级如果不使用app.ApplictaionServices.UseAutoShardingCreate()将不会自动创建表任务请注意,如果您是IIS代理那么请关闭应用程序池的固定回收和空闲回收设置为0,不然ShardingCore的创建表的任务可能不会生效

# 前言

ShardingCore主旨是增加efcore,针对efcore的分片方面进行增强,并且不对efcore的业务代码进行侵入。不解决数据库层面的问题,编写复杂sql如果在sql层面是慢的那么sharding-core也是无能为力的.

# 常见问题

因为当前架构师在当前dbcontext作为壳运行,crud会创建真实的dbcontext依托在当前dbcontext上,所以当前dbcontext目前crud都是可以的没有问题,但是如果遇到需要获取track或者其他的一些处理就不应该在当前dbcontext上处理,应该通过内部的DbContextExecutor来获取内部的DbContext来进行处理

# DbContext构造函数问题

请不要在DbContext构造函数内部调用会让model提前确定的方法比如

        public DefaultShardingDbContext(DbContextOptions<DefaultShardingDbContext> options) : base(options)
        {
            //切记不要在构造函数中使用会让模型提前创建的方法
            //ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
            //Database.SetCommandTimeout(30000);
        }
1
2
3
4
5
6

# 损耗

1.未分片对象查询,ShardingCore在针对未分片对象的查询上面进行了优化,单次的查询仅0.005ms损耗,性能为原生efcore的97%; 2.分片对象和原生efcore对象查询,在主键查询的情况下也就是只考虑ShardingCore损耗的情况下为单次0.06ms-0.08ms左右

当数据为瓶颈时分片后可以提高的性能是线性提升的,在数据库未成为读取数据库瓶颈时,整个查询两者差距不大

# 缺点

  • 本库的缺点是比较消耗链接,针对dbconnection的消耗比一般的链接要高,但是可以通过启动时候配置MaxQueryConnectionsLimit字段来限制单次查询的dbconnection的消耗,从而可以让用户可以进行控制连接数.
  • 目前不支持分表对象的Include,也不建议你对分表对象进行include,如果你需要操作分表对象请选择join方式而不是include
  • 三方批处理对象需要获取真实dbcontext后才可以支持
  • 因为不支持Include所以没必要给sharding对象进行导航属性设置(不支持导航属性)

# 为什么不用union或者union all

虽然union(all)在单表分表下面实现简单,支持的语句多但是性能随着表数量和表数据的增多性能逐渐下降更别说索引失效的场景,但是再多表join下面生成的sql将是不可控的,性能和索引将是一个大大的问题因为涉及到分表的多表不一定索引一直因为可能会出现数据偏向问题建立不同的所以结构导致索引失效不好优化、并且不支持分库等一系列问题

# 查询为读写分离支持追踪

如果本次查询是读写分离无论走的什么链接都支持对应对象的追踪

# GetHashCode

c#的gethashcode并不能直接用来取模,因为c#的GetHashCode会在程序启动的生命周期内同一个字符串是一样的,但是如果程序关闭后在启动那么就会和之前的hashcode不一致,所以这边建议使用sharding-core提供的ShardingCoreHelper.GetStringHashCode(shardingKeyStr)

# Group By

如果使用group by那么为了保证程序正常执行会在group by下判断如果没有order字段会将所有的select属性加上去,如果有order by那么必须和group by的select字段一样数目,如果group by 对对应属性进行了avg操作那么请对该属性同样进行count操作

# GUID

如果您是sqlserver 并且在用guid排序那么为了和数据库guid排序一致请知悉,sharding-core默认会将guid转成sqlguid去比较来保证和数据库一致的排序表现,但是未提供Nullable<Guid>的排序正确判断,如果需要可自行实现,下面是一个案例,默认ShardingCore已处理Guid的情况

/// <summary>
/// like this example
/// </summary>
/// <typeparam name="TShardingDbContext"></typeparam>
public class SqlServerNullableGuidCSharpLanguageShardingComparer:CSharpLanguageShardingComparer 
{
        public override int Compare(IComparable x, IComparable y, bool asc)
        {
            if (x is XXType xg && y is XXType yg)
            {
                return new XXFixedType(xg).SafeCompareToWith(new XXFixedType(yg), asc);
            }
            return base.Compare(x, y, asc);
        }
}

//configure
.ReplaceService<IShardingComparer,CSharpLanguageShardingComparer>()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

注意:如果您使用的框架不是本框架,那么请确认他的分表聚合是否是内存聚合,如果是内存聚合请确保他会有正确的guid排序在数据库和内存之间

# 自增Id

如果您在efcore配置了整型为自增那么请不要对自增字段设置为sharding字段因为会导致分表数据没办法正确分表,因为自增字段只有在正确插入到数据库后才会知道具体的值,所以不可以吧自增字段设置为分表/分库字段

# 性能优化(已经弃用表达式构建条件无需缓存)

如果您对程序的性能有要求建议您针对每个路由开启表达式缓存,并且自行实现多表判断表达式缓存,系统默认会在你启用路由表达式缓存后针对单个表达式比较进行缓存提高10倍编译性能


    public class SysUserSalaryVirtualTableRoute:AbstractShardingOperatorVirtualTableRoute<SysUserSalary,int>
    {
        //开启路由表达式缓存
        public override bool? EnableRouteParseCompileCache => true;

        //.....
    }
1
2
3
4
5
6
7
8

如果您需要使用一下方法需要注意

# EnsureCreated (建议使用migrate)

DbContext.Database.EnsureCreated()如果您需要使用这个接口请自行实现IMigrationsSqlGenerator

# 时间分表

如果您是时间分表的那么请一定要阅读高性能分页

上次编辑于: 2022年11月27日 15:22
贡献者: xuejiaming , xuejmnet , SilenceShui