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
}

浙公网安备 33010602011771号