397 lines
17 KiB
C#
397 lines
17 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using BenchmarkDotNet.Attributes;
|
|
using EFCore.BulkExtensions;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using ShardingCore;
|
|
using ShardingCore.Bootstrappers;
|
|
using ShardingCore.Core.VirtualDatabase.VirtualTables;
|
|
using ShardingCore.Core.VirtualRoutes.TableRoutes;
|
|
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
|
|
using ShardingCore.Core.VirtualTables;
|
|
using ShardingCore.Extensions;
|
|
using ShardingCore.Sharding.Abstractions;
|
|
using ShardingCore.TableExists;
|
|
using ShardingCoreBenchmark5x.NoShardingDbContexts;
|
|
using ShardingCoreBenchmark5x.ShardingDbContexts;
|
|
|
|
namespace ShardingCoreBenchmark5x
|
|
{
|
|
public class EFCoreCrud
|
|
{
|
|
private readonly DefaultDbContext _defaultDbContext;
|
|
private readonly DefaultShardingDbContext _defaultShardingDbContext;
|
|
private readonly IVirtualTableManager<DefaultShardingDbContext> _virtualTableManager;
|
|
private readonly IVirtualTable<Order> _virtualTable;
|
|
private readonly IRouteTailFactory _routeTailFactory;
|
|
private readonly IStreamMergeContextFactory<DefaultShardingDbContext> _streamMergeContextFactory;
|
|
public EFCoreCrud()
|
|
{
|
|
var services = new ServiceCollection();
|
|
|
|
services.AddDbContext<DefaultDbContext>(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=db1;Integrated Security=True;"), ServiceLifetime.Transient, ServiceLifetime.Transient);
|
|
services.AddLogging();
|
|
services.AddShardingDbContext<DefaultShardingDbContext>(ServiceLifetime.Transient, ServiceLifetime.Transient)
|
|
.AddEntityConfig(o =>
|
|
{
|
|
o.CreateShardingTableOnStart = true;
|
|
o.EnsureCreatedWithOutShardingTable = true;
|
|
o.AddShardingTableRoute<OrderVirtualTableRoute>();
|
|
})
|
|
.AddConfig(op =>
|
|
{
|
|
op.ConfigId = "c1";
|
|
op.UseShardingQuery((conStr, builder) =>
|
|
{
|
|
builder.UseSqlServer(conStr);
|
|
});
|
|
op.UseShardingTransaction((connection, builder) =>
|
|
{
|
|
builder.UseSqlServer(connection);
|
|
});
|
|
op.ReplaceTableEnsureManager(sp => new SqlServerTableEnsureManager<DefaultShardingDbContext>());
|
|
op.AddDefaultDataSource("ds0",
|
|
"Data Source=localhost;Initial Catalog=db2;Integrated Security=True;");
|
|
|
|
}).EnsureConfig();
|
|
|
|
var buildServiceProvider = services.BuildServiceProvider();
|
|
buildServiceProvider.GetRequiredService<IShardingBootstrapper>().Start();
|
|
ICollection<Order> orders = new LinkedList<Order>();
|
|
|
|
using (var scope = buildServiceProvider.CreateScope())
|
|
{
|
|
var defaultShardingDbContext = scope.ServiceProvider.GetService<DefaultDbContext>();
|
|
defaultShardingDbContext.Database.EnsureCreated();
|
|
if (!defaultShardingDbContext.Set<Order>().Any())
|
|
{
|
|
var begin = DateTime.Now.Date.AddDays(-8);
|
|
var now = DateTime.Now;
|
|
var current = begin;
|
|
int i = 0;
|
|
var x = new OrderStatusEnum[] { OrderStatusEnum.Failed, OrderStatusEnum.NotPay, OrderStatusEnum.Succeed };
|
|
while (current < now)
|
|
{
|
|
orders.Add(new Order()
|
|
{
|
|
Id = i.ToString(),
|
|
Amount = i,
|
|
Body = $"今天购买了的东西呀:{i}",
|
|
CreateTime = current,
|
|
Remark = $"这是我的备注哦备注哦备注哦:{i}",
|
|
Payer = Guid.NewGuid().ToString("n"),
|
|
OrderStatus = x[i % 3]
|
|
});
|
|
i++;
|
|
current = current.AddMilliseconds(100);
|
|
}
|
|
var sp = Stopwatch.StartNew();
|
|
defaultShardingDbContext.BulkInsert<Order>(orders.ToList());
|
|
sp.Stop();
|
|
Console.WriteLine($"批量插入订单数据:{orders.Count},用时:{sp.ElapsedMilliseconds}");
|
|
}
|
|
|
|
}
|
|
using (var scope = buildServiceProvider.CreateScope())
|
|
{
|
|
var defaultShardingDbContext = scope.ServiceProvider.GetService<DefaultShardingDbContext>();
|
|
if (!defaultShardingDbContext.Set<Order>().Any())
|
|
{
|
|
var sp = Stopwatch.StartNew();
|
|
var bulkShardingEnumerable = defaultShardingDbContext.BulkShardingTableEnumerable(orders.ToList());
|
|
foreach (var keyValuePair in bulkShardingEnumerable)
|
|
{
|
|
keyValuePair.Key.BulkInsert(keyValuePair.Value.ToList());
|
|
}
|
|
sp.Stop();
|
|
Console.WriteLine($"批量插入订单数据:{orders.Count},用时:{sp.ElapsedMilliseconds}");
|
|
}
|
|
}
|
|
_defaultDbContext = ShardingContainer.GetService<DefaultDbContext>();
|
|
_defaultShardingDbContext = ShardingContainer.GetService<DefaultShardingDbContext>();
|
|
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<DefaultShardingDbContext>>();
|
|
_virtualTable = _virtualTableManager.GetVirtualTable<Order>();
|
|
_routeTailFactory= ShardingContainer.GetService<IRouteTailFactory>();
|
|
_streamMergeContextFactory =
|
|
ShardingContainer.GetService<IStreamMergeContextFactory<DefaultShardingDbContext>>();
|
|
var queryable1 = _defaultShardingDbContext.Set<Order>().Where(o => o.Id == "0");
|
|
_virtualTable.RouteTo(new ShardingTableRouteConfig(queryable: queryable1));
|
|
var queryable = _defaultShardingDbContext.Set<Order>().Where(o => o.Id == "1000");
|
|
_virtualTable.RouteTo(new ShardingTableRouteConfig(queryable: queryable));
|
|
}
|
|
|
|
|
|
[Params(10)]
|
|
public int N;
|
|
|
|
[Benchmark]
|
|
public async Task NoShardingFirstOrDefaultAsync()
|
|
{
|
|
for (int i = 0; i < N; i++)
|
|
{
|
|
var next = new Random().Next(1, 3000000).ToString();
|
|
var firstOrDefaultAsync = await _defaultDbContext.Set<Order>().FirstOrDefaultAsync(o => o.Id == next);
|
|
}
|
|
}
|
|
[Benchmark]
|
|
public async Task ShardingFirstOrDefaultAsync()
|
|
{
|
|
for (int i = 0; i < N; i++)
|
|
{
|
|
var next = new Random().Next(1, 3000000).ToString();
|
|
var firstOrDefaultAsync = await _defaultShardingDbContext.Set<Order>().FirstOrDefaultAsync(o => o.Id == next);
|
|
}
|
|
}
|
|
//[Benchmark]
|
|
//public async Task NoShardingIndexFirstOrDefaultAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(1000000, 7000000).ToString();
|
|
// var firstOrDefaultAsync = await _defaultDbContext.Set<Order>().FirstOrDefaultAsync(o => o.Id == next);
|
|
// }
|
|
//}
|
|
|
|
|
|
//[Benchmark]
|
|
//public async Task ShardingIndexFirstOrDefaultAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(1000000, 7000000).ToString();
|
|
// var firstOrDefaultAsync = await _defaultShardingDbContext.Set<Order>().FirstOrDefaultAsync(o => o.Id == next);
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task NoShardingNoIndexFirstOrDefaultAsync100w()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var firstOrDefaultAsync = await _defaultDbContext.Set<Order>().FirstOrDefaultAsync(o => o.Amount == 1000000);
|
|
// }
|
|
//}
|
|
|
|
|
|
//[Benchmark]
|
|
//public async Task ShardingNoIndexFirstOrDefaultAsync100w()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var firstOrDefaultAsync = await _defaultShardingDbContext.Set<Order>().FirstOrDefaultAsync(o => o.Amount == 1000000);
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task NoShardingNoIndexCountAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var firstOrDefaultAsync = await _defaultDbContext.Set<Order>().CountAsync(o => o.Amount == 3000000);
|
|
// }
|
|
//}
|
|
|
|
|
|
//[Benchmark]
|
|
//public async Task ShardingNoIndexCountASYNC()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var firstOrDefaultAsync = await _defaultShardingDbContext.Set<Order>().CountAsync(o => o.Amount == 3000000);
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task NoShardingNoIndexFirstOrDefaultAsync600w()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var firstOrDefaultAsync = await _defaultDbContext.Set<Order>().FirstOrDefaultAsync(o => o.Amount == 6000000);
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task ShardingNoIndexFirstOrDefaultAsync600w()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var firstOrDefaultAsync = await _defaultShardingDbContext.Set<Order>().FirstOrDefaultAsync(o => o.Amount == 6000000);
|
|
// }
|
|
//}
|
|
|
|
|
|
//[Benchmark]
|
|
//public async Task NoShardingNoIndexLikeToListAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(1, 8000000).ToString();
|
|
// var firstOrDefaultAsync = await _defaultDbContext.Set<Order>().Where(o => o.Body.Contains(next)).FirstOrDefaultAsync();
|
|
// }
|
|
//}
|
|
|
|
|
|
//[Benchmark]
|
|
//public async Task ShardingNoIndexLikeToListAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(1, 8000000).ToString();
|
|
// var firstOrDefaultAsync = await _defaultShardingDbContext.Set<Order>().Where(o => o.Body.Contains(next)).FirstOrDefaultAsync();
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task NoShardingNoIndexToListAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(5000000, 7000000);
|
|
// var firstOrDefaultAsync = await _defaultDbContext.Set<Order>().Where(o => o.Amount == next).ToListAsync();
|
|
// }
|
|
//}
|
|
|
|
|
|
//[Benchmark]
|
|
//public async Task ShardingNoIndexToListAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(5000000, 7000000);
|
|
// var firstOrDefaultAsync = await _defaultShardingDbContext.Set<Order>().Where(o => o.Amount == next).ToListAsync();
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public void ShardingRouteFirstOrDefault()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(1000000, 7000000).ToString();
|
|
// var queryable = _defaultShardingDbContext.Set<Order>().Where(o => o.Id == next);
|
|
// _virtualTable.RouteTo(new ShardingTableRouteConfig(queryable: queryable));
|
|
// }
|
|
//}
|
|
//private static readonly string[] aa = new string[] { "a", "b", "c", "d" };
|
|
//[Benchmark]
|
|
//public void ShardingCreateDbContextFirstOrDefault()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
|
|
// var routeTail = _routeTailFactory.Create(aa[i % 4]);
|
|
// var dbContext = _defaultShardingDbContext.GetDbContext("ds0", true, routeTail);
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task ShardingWhereFirstOrDefaultAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(1000000, 7000000).ToString();
|
|
// var firstOrDefaultAsync = await _defaultShardingDbContext.Set<Order>().Where(o => o.Id == next).FirstOrDefaultAsync();
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task ShardingCreateStreamMergeContext()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(1000000, 7000000).ToString();
|
|
// var queryable = _defaultShardingDbContext.Set<Order>().Where(o => o.Id == next);
|
|
// var firstOrDefaultAsync = _streamMergeContextFactory.Create(queryable, _defaultShardingDbContext);
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task ShardingCreateEnumerableQuery()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(1000000, 7000000).ToString();
|
|
// var queryable = _defaultShardingDbContext.Set<Order>().Where(o => o.Id == next);
|
|
// new EnumerableQuery<Order>(queryable.Expression);
|
|
// }
|
|
//}
|
|
//private TResult GenericShardingDbContextMergeExecute<TResult>(IQueryable<Order> queryable)
|
|
//{
|
|
// //{
|
|
// // var queryEntityType = query.GetQueryEntityType();
|
|
// //var newStreamMergeEngineType = streamMergeEngineType.MakeGenericType(shardingDbContext.GetType(), queryEntityType);
|
|
|
|
// //// {
|
|
|
|
// //// //获取所有需要路由的表后缀
|
|
// //// var startNew = Stopwatch.StartNew();
|
|
// //// for (int i = 0; i < 10000; i++)
|
|
// //// {
|
|
// //// var streamEngine = ShardingCreatorHelper.CreateInstance(newStreamMergeEngineType, query, shardingDbContext);
|
|
// //// }
|
|
// //// startNew.Stop();
|
|
// //// var x = startNew.ElapsedMilliseconds;
|
|
// //// }
|
|
// //{
|
|
|
|
// // //获取所有需要路由的表后缀
|
|
// // var startNew1 = Stopwatch.StartNew();
|
|
// // for (int i = 0; i < 10000; i++)
|
|
// // {
|
|
// // var streamEngine = Activator.CreateInstance(newStreamMergeEngineType, query, shardingDbContext);
|
|
// // }
|
|
// // startNew1.Stop();
|
|
// // var x = startNew1.ElapsedMilliseconds;
|
|
// //}
|
|
// // var methodName = async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult);
|
|
// // var streamEngineMethod = newStreamMergeEngineType.GetMethod(methodName);
|
|
// // if (streamEngineMethod == null)
|
|
// // throw new ShardingCoreException($"cant found InMemoryAsyncStreamMergeEngine method [{methodName}]");
|
|
// // var @params = async ? new object[] { cancellationToken } : new object[0];
|
|
// //}
|
|
|
|
// {
|
|
// var queryEntityType = queryable.Expression.GetQueryEntityType();
|
|
// var newStreamMergeEngineType = streamMergeEngineType.MakeGenericType(shardingDbContext.GetType(), queryEntityType);
|
|
// var streamEngine = Activator.CreateInstance(newStreamMergeEngineType, query, shardingDbContext);
|
|
// var methodName = async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult);
|
|
// var streamEngineMethod = newStreamMergeEngineType.GetMethod(methodName);
|
|
// if (streamEngineMethod == null)
|
|
// throw new ShardingCoreException($"cant found InMemoryAsyncStreamMergeEngine method [{methodName}]");
|
|
// var @params = async ? new object[] { cancellationToken } : new object[0];
|
|
// return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(streamEngine, @params);
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task NoShardingNoTrackingFirstOrDefaultAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(1, 3000000).ToString();
|
|
// var firstOrDefaultAsync = await _defaultDbContext.Set<Order>().AsNoTracking().FirstOrDefaultAsync(o => o.Id == next);
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task ShardingNoTrackingFirstOrDefaultAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var next = new Random().Next(1, 3000000).ToString();
|
|
// var firstOrDefaultAsync = await _defaultShardingDbContext.Set<Order>().AsNoTracking().FirstOrDefaultAsync(o => o.Id == next);
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task NoShardingCountAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var firstOrDefaultAsync = await _defaultDbContext.Set<Order>().CountAsync();
|
|
// }
|
|
//}
|
|
//[Benchmark]
|
|
//public async Task ShardingCountAsync()
|
|
//{
|
|
// for (int i = 0; i < N; i++)
|
|
// {
|
|
// var firstOrDefaultAsync = await _defaultShardingDbContext.Set<Order>().CountAsync();
|
|
// }
|
|
//}
|
|
|
|
}
|
|
}
|