ORM框架-SqlSugar-分表

参考资料:SqlSugar分表 - yswenli - 博客园

解决性能问题:

索引:30W条数据内,效果很明显。但是千万级的数据存储的时候,索引也无能为力。索引也只是解决查询问题,增删改还是有影响

其他的办法:分区,分表,分库,读写分开,缓存

拆分:

任何方案在大体量的存储中,都是渺小的。

一,数据的存储拆分:分库,分表,把存储化整为零,大表拆分小表,大库变小库

  每个表中或者是每个库中的数据存储都是不一样的

二,数据库的操作拆分:增删改(写),查(读),读写分离

 数据库:2-8原则:

20%的数据操作:增删改

80%的操作:查询

查询动作:由多个服务器来支撑,做到了负载均衡

写库需要把操作同步到 查询库中;

主库:增删改

从库:查

一主多从:

数据如何复制,采用的是数据库日志(对于每一个操作都有1个记录)

1,数据同步有延迟,有办法解决的。

2,

 

数据库的分表,化整为零,自己做,定义规则,表不仅要存储数据,还要定义规则来判断数据具体存储在哪个表中;

规则来确定具体要操作的数据。

1,自动分表:简单,通过配置来完成。比如按年份,月份

2,自定义分表:自己 扩展规则

1,分表

1.1 分表结构结果展示:

 1.2 分表的类

按时间分表的类:

    [SplitTable(SplitType.Year)]//按年分表,分表后,多个表命名,需要一个代表性命名
    [SugarTable("TighteningResultSubTableYear_{day}_{month}_{year}")]//生成表名格式,3个变量必须要有
    public partial class TighteningResultSubTableYear
    {
        public TighteningResultSubTableYear() { }

        //使用自动分表,主键不能设置自增
        [SugarColumn(IsIdentity = false, IsPrimaryKey = true)]
        public int ID { get; set; }
        public string TighteningID { get; set; }
        [SugarColumn(IsNullable = true)]//是否可以为空
        public string ProductName { get; set; }
        [SugarColumn(IsNullable = true)]//是否可以为空
        public string ProductSN { get; set; }
        [SugarColumn(IsNullable = true)]//是否可以为空
        public string StationCode { get; set; }
        [SugarColumn(IsNullable = true)]//是否可以为空
        public string StationName { get; set; }
        [SugarColumn(IsNullable = true)]//是否可以为空
        public string PsetName { get; set; }
        [SugarColumn(IsNullable = true)]//是否可以为空
        public string BoltNumber { get; set; }
        public string TighteningStatus { get; set; }
        //public string ResultDataTime { get; set; }
        [SplitField]//分表字段,在插入的时候会根据这个字段插入哪个表,在更新删除的时候用这个字段找出相关表
        public DateTime? ResultDataTime { get; set; }
。。。

    }

自定义分表的类

    [SplitTable(SplitType._Custom01)]//自定义分表
    [SugarTable("TightengingResultSubTableArea")]//生成表名格式,
    public class TightengingResultSubTableArea
    {
            public TightengingResultSubTableArea() { }

            //使用自动分表,主键不能设置自增
            [SugarColumn(IsIdentity = false, IsPrimaryKey = true)]
            public int ID { get; set; }
            public string TighteningID { get; set; }
            [SugarColumn(IsNullable = true)]//是否可以为空
            public string ProductName { get; set; }
            [SugarColumn(IsNullable = true)]//是否可以为空
            public string ProductSN { get; set; }
            [SugarColumn(IsNullable = true)]//是否可以为空
            public string StationCode { get; set; }

            [SplitField]//分表字段
            public string StationName { get; set; }
            [SugarColumn(IsNullable = true)]//是否可以为空
。。。

    }

1.3 分表写入数据代码:

    public class AutoSubTableDemo : ISplitTableService //如果是自定义分表,需要这个接口
    {


        #region 按时间自动分表

        public static void ShowSubTable()
        {
            ConnectionConfig connectionConfig = new ConnectionConfig()
            {
                //注意要填写需要创建的数据库名称
                ConnectionString =
                    "Data Source=KDE49AE3P78OP7D;Initial Catalog=HolyBoltSystemDB_New;User ID=sa;Password=123",
                IsAutoCloseConnection = true,
                DbType = DbType.SqlServer
            };

            //准备要插入到表中的数据
            List<TighteningResultSubTableYear> addList = new List<TighteningResultSubTableYear>();
            for (int i = 1; i < 10000; i++)
            {
                int seed = i % 10; //模拟10年的数据,值:0-9
                addList.Add(new TighteningResultSubTableYear()
                {
                    ID = i,
                    ResultDataTime = DateTime.Now.AddYears(seed),
                    ProductSN = $"SN_{new Random().Next(1, 10)}",
                    FinalTorque = i.ToString(),
                    TorqueMin = (i * 0.95).ToString(),
                    TorqueMax = (i * 1.05).ToString(),
                    FinalAngle = (i * 2).ToString(),
                    TighteningID = i.ToString(),
                    TighteningStatus = new[] {"OK", "NG"}[new Random().Next(0, 2)]
                });
            }

            //SqlSugarClient:链接数据库的对象
            using (SqlSugarClient db = new SqlSugarClient(connectionConfig))
            {
                //如果不存在则创建数据,存在则不会重复创建
                {
                    db.DbMaintenance.CreateDatabase(); //注意:Oracle和个别国产的不支持该方法
                }

                //根据实体类创建表
                {
                    db.CodeFirst
                        .SplitTables() //表示分表
                        .InitTables(typeof(TighteningResultSubTableYear)); //如果一张表都没有,会初始化一张表
                }
                //清除所有的数据
                {

                    DateTime beginDate = DateTime.Now.AddYears(-1);
                    DateTime endDate = DateTime.Now.AddYears(20);
                    var list = db.Queryable<TighteningResultSubTableYear>().SplitTable(beginDate, endDate).ToList();
                    List<TighteningResultSubTableYear> delList = db.Queryable<TighteningResultSubTableYear>()
                        .SplitTable(beginDate, endDate).ToList();
                    db.Deleteable<TighteningResultSubTableYear>(delList).SplitTable().ExecuteCommand();
                }
                //插入数据
                {
                    long iResult = db.Insertable(addList)
                        .SplitTable() //插入数据的时候也要启用分表
                        .ExecuteCommand();
                }
            }

        }

        #endregion


        #region 自定义分表

        //如果数据保存的是字典的Value,就使用字典的Key作为表的后缀
        public static Dictionary<string, string> _AreaDictionary;
        static AutoSubTableDemo()
        {
            _AreaDictionary=new Dictionary<string, string>()
            {
                {"StationName_suibian1" ,"StationName1"},
                {"StationName_suibian2" ,"StationName2"},
                {"StationName_suibian3" ,"StationName3"},
                {"StationName_suibian4" ,"StationName4"},
                {"StationName_suibian5" ,"StationName5"},
            };
        }

        public static void ShowCustomSubTable()
        {
            ConnectionConfig connectionConfig = new ConnectionConfig()
            {
                //注意要填写需要创建的数据库名称
                ConnectionString =
                    "Data Source=KDE49AE3P78OP7D;Initial Catalog=HolyBoltSystemDB_New;User ID=sa;Password=123",
                IsAutoCloseConnection = true,
                DbType = DbType.SqlServer
            };

            //准备要插入到表中的数据
            List<TightengingResultSubTableArea> addList = new List<TightengingResultSubTableArea>();
            for (int i = 1; i < 10000; i++)
            {
                int seed = i % 10; //模拟10年的数据,值:0-9
                addList.Add(new TightengingResultSubTableArea()
                {
                    ID = i,
                    ResultDataTime = DateTime.Now.AddYears(seed),
                    ProductSN = $"SN_{new Random().Next(1, 10)}",
                    FinalTorque = i.ToString(),
                    TorqueMin = (i * 0.95).ToString(),
                    TorqueMax = (i * 1.05).ToString(),
                    FinalAngle = (i * 2).ToString(),
                    TighteningID = i.ToString(),
                    TighteningStatus = new[] {"OK", "NG"}[new Random().Next(0, 2)],
                    StationName = $"StationName{new Random().Next(1, 6)}",
                });
            }

            //SqlSugarClient:链接数据库的对象
            using (SqlSugarClient db = new SqlSugarClient(connectionConfig))
            {
                //把我们自己定义好的分表规则,赋予给SqlSugar
                db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService=new AutoSubTableDemo();//自定义的分表规则

                //如果不存在则创建数据,存在则不会重复创建
                {
                    db.DbMaintenance.CreateDatabase(); //注意:Oracle和个别国产的不支持该方法
                }

                //根据实体类创建表
                {
                    db.CodeFirst
                        .SplitTables() //表示分表
                        .InitTables(typeof(TightengingResultSubTableArea)); //如果一张表都没有,会初始化一张表
                }

                //插入数据
                {
                    long iResult = db.Insertable(addList)
                        .SplitTable() //插入数据的时候也要启用分表
                        .ExecuteCommand();
                }
            }

        }

        /// <summary>
        /// 获取所有的表名称
        /// </summary>
        /// <param name="db"></param>
        /// <param name="EntityInfo"></param>
        /// <param name="tableInfos"></param>
        /// <returns></returns>
        public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo,
            List<DbTableInfo> tableInfos)
        {
            List<SplitTableInfo> result = new List<SplitTableInfo>();
            foreach (var item in tableInfos)//变量所有的表
            {
                if (item.Name.Contains("_Area_"))
                {
                    SplitTableInfo data=new SplitTableInfo()
                    {
                        TableName = item.Name
                    };
                    result.Add(data);
                }
            }

            return result.OrderBy(it => it.TableName).ToList();
        }

        /// <summary>
        /// 获取表名称
        /// </summary>
        /// <param name="db"></param>
        /// <param name="EntityInfo"></param>
        /// <returns></returns>
        public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo)
        {
            return EntityInfo.DbTableName + "_Aera";
        }

        /// <summary>
        /// 获取表名称
        /// </summary>
        /// <param name="db"></param>
        /// <param name="EntityInfo"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType type)
        {
            return EntityInfo.DbTableName + "_Aera";
        }

        /// <summary>
        /// 获取表名称
        /// </summary>
        /// <param name="db"></param>
        /// <param name="entityInfo"></param>
        /// <param name="splitType"></param>
        /// <param name="fieldValue"></param>
        /// <returns></returns>
        public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
        {
            KeyValuePair<string, string> keyPar =
                _AreaDictionary.FirstOrDefault(c => fieldValue.ToString().Contains(c.Value));
            return entityInfo.DbTableName + "_Area_" + keyPar.Key;
        }

        /// <summary>
        /// 根据表名称获取数据
        /// </summary>
        /// <param name="db"></param>
        /// <param name="entityInfo"></param>
        /// <param name="splitType"></param>
        /// <param name="entityValue"></param>
        /// <returns></returns>
        public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue)
        {
            var splitColumn = entityInfo.Columns.FirstOrDefault(it =>
                it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null);
            return splitColumn.PropertyInfo.GetValue(entityValue,null);
        }

        #endregion
    }

  

posted @ 2025-03-21 16:53  包子789654  阅读(176)  评论(1)    收藏  举报