EF Core性能优化技巧
代码层面的优化
1. 使用实例池
EFCore2.0 为DbContext引入新的注册方式:透明地注册了 DbContext实例池,使用这种方式可以避免始终创建新的实例,EF Core 将重置其状态并将其存储在内部池中;当下次请求新的实例时,将返回该共用实例,而不是设置新的实例
使用示例:
services.AddDbContext<HandshakesWebDBContext>(options => options.UseSqlServer(connectionConfiguration.WebDBConnection));
替换为
builder.Services.AddDbContextPool<HandshakesWebDBContext>(options => options.UseSqlServer(connectionConfiguration.WebDBConnection), poolSize: 80);
//注意设置最大连接数,一旦超过默认配置的连接池最大数量,会回退到按需创建实例的行为
基准测试(官方) 测试代码:
方法 | 数量 | 平均值 | 错误 | 标准偏差 | Gen 0 | Gen 1 | Gen 2 | 已分配 |
---|---|---|---|---|---|---|---|---|
WithoutContextPooling | 1 | 701.6 us | 26.62 us | 78.48 us | 11.7188 | - | - | 50.38 KB |
WithContextPooling | 1 | 350.1 us | 6.80 us | 14.64 us | 0.9766 | - | - | 4.63 KB |
注意事项:虽然在大部分情况下这种做法对性能的提升可能并不是非常明显,但是这是一种好的实践方式,避免资源浪费的同时对性能带来一定的提升。
2. 使用拆分查询
了解什么是 笛尔卡乘积 ?
通俗地来讲指的是从两个集合(Set)中的元素组成新的配对集合 以麦当劳套餐来比喻,门店将汉堡线和饮品线上的每个产品集合组成一个新的套餐会有多少种套餐
在数据库中的表现形式正是联表查(join)操作 两个表在数据量不是很大的情况下查询来讲可能对性能影响模棱两可 但是对于一些因业务需求日益增加列的大宽表以及数据存量过大的表来讲就会产生查询过慢以及数据冗余的问题
尤其适合一对多且子表数据量较大的场景。
看一段Linq代码:
var data = ctx.As
.Include(x => x.Bs)
.Include(x => x.Cs)
.ThenInclude(x => x.D1s)
.Include(x => x.Cs)
.ThenIncude(x => x.C1s)
.ThenInclude(x=>x.D2s)
.ToList();
监控查看生成的Sql语句:
SELECT [A].[Id], [A].[Name],
[B].[Id], [B].[AId], [B].[Name],
[C].[Id], [C].[AId], [C].[Name],
[D1].[Id], [D1].[CId], [D1].[Name],
[C1].[Id], [C1].[CId], [C1].[Name],
[D2].[Id], [D2].[C1Id], [D2].[Name]
FROM [As] AS [A]
LEFT JOIN [Bs] AS [B] ON [A].[Id] = [B].[AId]
LEFT JOIN [Cs] AS [C] ON [A].[Id] = [C].[AId]
LEFT JOIN [D1s] AS [D1] ON [C].[Id] = [D1].[CId]
LEFT JOIN [C1s] AS [C1] ON [C].[Id] = [C1].[CId]
LEFT JOIN [D2s] AS [D2] ON [C1].[Id] = [D2].[C1Id]
毫无疑问,这一段糟糕的sql语句,假设每张表的数据量都很大的情况下,这对查询无疑是一种很大的负担,如果条件再复杂一点,对整个语句的分析也是很糟糕的。关于阿里开发规范中定义超过3张表的join查询是被禁止的 (未查证),这个可能只是为了开发规范和管理,从技术角度出发,其实是没有这样的原则性问题的。
解决方案:使用SplitQuery,从字面意义就可以理解,即将这些join查询拆分成单个查询来执行
示例代码(推荐):
var data = ctx.As
.Include(x => x.Bs)
.Include(x => x.Cs)
.ThenInclude(x => x.D1s)
.Include(x => x.Cs)
.ThenIncude(x => x.C1s)
.ThenInclude(x=>x.D2s)
.AsSplitQuery() //设置为拆分查询
.ToList();
当然也可以在全局进行配置 (但是一般不推荐这样做,最好根据每个查询的实际情况,使用上面推荐的方式)
builder.Services.AddDbContext<CRSGEntityDbContext>(options => options.UseSqlServer(builder.Configuration["ConnectionStrings:FiinGroupDB"], o => o.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)));
生成的sql
SELECT [a].[Id], [a].[OtherColumns]
FROM [As] AS [a]
SELECT [b].[Id], [b].[AId], [b].[OtherColumns]
FROM [Bs] AS [b]
INNER JOIN [As] AS [a] ON [b].[AId] = [a].[Id]
SELECT [c].[Id], [c].[AId], [c].[OtherColumns]
FROM [Cs] AS [c]
INNER JOIN [As] AS [a] ON [c].[AId] = [a].[Id]
SELECT [d1].[Id], [d1].[CId], [d1].[OtherColumns]
FROM [D1s] AS [d1]
INNER JOIN [Cs] AS [c] ON [d1].[CId] = [c].[Id]
WHERE [c].[AId] IN (SELECT [a].[Id] FROM [As] AS [a])
SELECT [c1].[Id], [c1].[CId], [c1].[OtherColumns]
FROM [C1s] AS [c1]
INNER JOIN [Cs] AS [c] ON [c1].[CId] = [c].[Id]
WHERE [c].[AId] IN (SELECT [a].[Id] FROM [As] AS [a])
SELECT [d2].[Id], [d2].[C1Id], [d2].[OtherColumns]
FROM [D2s] AS [d2]
INNER JOIN [C1s] AS [c1] ON [d2].[C1Id] = [c1].[Id]
WHERE [c1].[CId] IN (SELECT [c].[Id] FROM [Cs] AS [c] WHERE [c].[AId] IN (SELECT [a].[Id] FROM [As] AS [a]))
可以看到查询被拆分成了独立的语句,逻辑更加清晰,对于数据库来说执行效率也会更好。
注意事项:虽然拆分查询可以通过避免笛尔卡爆炸带来的性能问题,但是也需要根据实际的查询场景来决定是否使用,例如,需要对数据进行排序,分页,分组等操作的时候,为了保证查询结果的正确性,就需要考虑是否要使用拆分查询
关联话题:关于懒加载,其实懒加载的问题原因就等同于在循环中执行sql语句,示例代码:
//在没有显示加载的情况下,直接循环查询子对象
foreach (var blog in context.Blogs.ToList())
{
foreach (var post in blog.Posts)
{
Console.WriteLine($"Blog {blog.Url}, Post: {post.Title}");
}
}
观察sql日志:
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [b].[BlogId], [b].[Rating], [b].[Url]
FROM [Blogs] AS [b]
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (5ms) [Parameters=[@__p_0='1'], CommandType='Text', CommandTimeout='30']
SELECT [p].[PostId], [p].[BlogId], [p].[Content], [p].[Title]
FROM [Post] AS [p]
WHERE [p].[BlogId] = @__p_0
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (1ms) [Parameters=[@__p_0='2'], CommandType='Text', CommandTimeout='30']
SELECT [p].[PostId], [p].[BlogId], [p].[Content], [p].[Title]
FROM [Post] AS [p]
WHERE [p].[BlogId] = @__p_0
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (1ms) [Parameters=[@__p_0='3'], CommandType='Text', CommandTimeout='30']
SELECT [p].[PostId], [p].[BlogId], [p].[Content], [p].[Title]
FROM [Post] AS [p]
WHERE [p].[BlogId] = @__p_0
... and so on
正确的做法即使用Include或者Load显示加载数据。
3. 使用批处理语句
批处理语句是EFCore7 版本中更新的重要功能,解决了以往版本需要借助第三方库来实现数据的批量更新,删除操作,而且在性能上带来了更大的提升
3.1 批量删除
之前版本的做法(不借助第三方库)
foreach (var blog in context.Blogs.Where(b => b.Rating < 3))
{
context.Blogs.Remove(blog);
}
context.SaveChanges();
使用ExecuteDelete,无论是从语法上还是性能上,批处理操作都优于前者。
context.Blogs.Where(b => b.Rating < 3).ExecuteDelete();
如果是EFCore版本低于7.0,也可以使用直接执行sql语句 ExecuteSqlRaw 的方式来进行操作
context.Database.ExecuteSqlRaw("DELETE FROM [Blogs] WHERE [Rating] < 3");
3.2 批量更新
用法与Delete 基本相同
context.Blogs
.Where(b => b.Rating < 3)
.ExecuteUpdate(setters => setters.SetProperty(b => b.IsVisible, false));
注意事项:目前仅支持关系型数据库,而且需要由于是及时发送上下文请求,所以如果要支持事务,需要使用显示事务来与其他代码组合
4. 使用非跟踪查询
这个比较简单,在你不需要对查询结果进行任何更新操作的场景下,尽量使用非跟踪查询
var blogs = context.Blogs
.AsNoTracking()
.ToList();
或者
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var blogs = context.Blogs.ToList();
测试代码
//代码执行前已对数据库进行预热处理
//执行5次
double elapsedTime4 = MeasureTime(() => context.Blogs.FirstOrDefault(x => x.Id == 1), 5);
double elapsedTime5 = MeasureTime(() => context.Blogs.AsNoTracking().FirstOrDefault(x => x.Id == 1), 5);
Console.WriteLine($"Tracked time took : {elapsedTime4} ms");
Console.WriteLine($"AsNoTracking() time took : {elapsedTime5} ms");
//Consoles:
//Tracked time took : 318.26 ms
//AsNoTracking() time took : 229.86 ms
5. 仅投影需要的字段
严格意义上来讲这是一个意识问题,大多数情况下,为了节省代码量,可以直接使用DataSet 定义的对象来直接进行查询,或者使用Include加载关联表数据,但是在遇到大量数据查询或大量的表连接查询的时候,精准的属性投影对性能就会起到很大的影响
示例代码:
var data = ctx.As
.Where(x => x.Name.StartWith("xxx"))
.ToList();
foreach (var item in data.Bs)
{
Console.WriteLine($"Name :{item.Name},Id: {item.Id}");
}
上述代码中,我们仅需要查询主表及子表的id和name信息,但是却加载了所有的相关的主表和子表字段,这对性能是一种浪费
解决方案:通过Select投影需要查询的字段
var data = ctx.As
.Where(x => x.Id=1)
.Select(x => new {x.Id, x.Name})
.ToList();
个人习惯性做法
//1,不依赖于数据库外键的设置
var query = from b in context.Blogs
join c in context.Comments on b.blogId equals c.blogId
join d in context.Posts on d.commentId equals c.commentId
select new A{blogId = b.blogId,postId = d.postId,postValue = d.postValue}
这种做法对多表联查和大数据量的查询很有用 ,但需要注意的是这种做法并不适合需要更新数据的场景,因为 EF 的更改跟踪仅适用于实体实例。
6. 尽量使用异步方法
EFCore 基本上对所有同步操作方法都提供了对应的异步方法,尽量使用他们避免阻塞,减少对线程的需要和必须发生的线程上下文切换的次数,从而提升性能。
//ToListAsync
var data = await context.blogs.ToListAsync();
//FirstOrDefaultAsync
var item = await context.blogs.FirstOrDefaultAsync(it => it.Id == 1);
item.point=2;
//SaveChangesAsync
await context.SaveChangesAsync();
//AsAsyncEnumerable
var groupedHighlyRatedBlogs = await context.Blogs
.AsQueryable()
.Where(b => b.Rating > 3) // server-evaluated
.AsAsyncEnumerable()
.GroupBy(b => b.Rating) // client-evaluated
.ToListAsync();
异步编程在efcore中在大多数情况被推荐使用,但是需要注意避免使用异步方法查询文本或二进制数据类型的内容,这样反而会引起性能问题(sqlclient的问题),issue报告: EF Core - Memory and performance issues with async methods Reading large data (binary, text) asynchronously is extremely slow
避免混合使用同步和异步方法,当你的程序请求量较大的时候,很可能导致连接池耗尽,从而引起的性能问题。
7. 使用Find查找单个目标数据
设计为在已知主键时高效查找单个实体。 Find 首先检查实体是否已被跟踪,如果是,则立即返回该实体。 只有当未在本地跟踪实体时,才执行数据库查询,而First/FirstOrDefault会立即查询数据库。
//代码执行前已对数据库进行预热处理
double elapsedTime4 = MeasureTime(() => context.blogs.Find(1);
double elapsedTime5 = MeasureTime(() => context.blogs.Find(1);
Console.WriteLine($"Find() first time took : {elapsedTime4} ms");
Console.WriteLine($"Find() second time took : {elapsedTime5} ms");
//Consoles:
//Find() first time took : 268.41 ms
//Find() second time took : 0.16 ms
注意,只能通过键查询的时候可以用。
8. 使用Any判断数据内容
在检查某些数据是否存在的时候,优先使用Any,这样在匹配到第一条数据后,查询就会停止,First因为需要返回数据,增加了数据传输和对象实例化的开销,Count则需要扫描表
double elapsedTime1 = MeasureTime(() => context.Blogs.Any(it => it.Id == 1));
double elapsedTime2 = MeasureTime(() => context.Blogs.Count(it => it.Id == 1), 1);
double elapsedTime3 = MeasureTime(() => context.Blogs.FirstOrDefault(it => it.Id == 1), 1);
Console.WriteLine($"Any() time took: {elapsedTime1} ms");
Console.WriteLine($"Count() time took: {elapsedTime2} ms");
Console.WriteLine($"FirstOrDefault() time took: {elapsedTime3} ms");
//Consoles:
//Any() time took: 237.42 ms
//Count() time took: 239.69 ms
//FirstOrDefault() time took: 258.28 ms
9.使用流式处理
首先了解什么是缓冲和流式处理
- 缓冲:将需要的数据全部加载到内存中,用于后续的业务逻辑处理
- 流式处理:按需获取需要的数据并应用到后续的逻辑处理中
形象的理解,缓冲用水桶把水挑起来,然后倒进缸里,流式处理就是用一根水管把水抽到缸里
原则上,流式处理查询的内存要求是固定的:无论查询返回 1 行还是 1000 行,内存要求都相同。另一方面,返回的行数越多,缓冲查询需要的内存越多。 对于产生大型结果集的查询,这可能是一个重要的性能因素。 反之,如果你的查询结果量很小,那么使用缓冲的效果可能返回会更好。
//一次性将数据加载出来
var blogsList = context.Posts.Where(p => p.Title.StartsWith("A")).ToList();
var blogsArray = context.Posts.Where(p => p.Title.StartsWith("A")).ToArray();
//使用流式处理,每次处理一行
foreach (var blog in context.Posts.Where(p => p.Title.StartsWith("A")))
{
//do some things...
SomeDotNetMethod(blog)
}
// 也可以使用AsEnumerable实现
var doubleFilteredBlogs = context.Posts
.Where(p => p.Title.StartsWith("A")) // 执行数据库查询
.AsEnumerable()
.Where(p => SomeDotNetMethod(p)); //执行客户端操作
流式处理适合处理大量数据需要进行某些业务逻辑的加工或执行,但是数据库又无法支持响应的方法或函数,这个时候可以适用流式处理来进行操作。
10. 使用SQL查询
在某些特殊的情况下,例如一些复杂的sql查询,无法直接使用linq语法来实现的,EFCore也支持直接使用SQL语句进行查询或数据更新操作
10.1. 基本查询(实体)
场景:最终返回的结果与Dataset中定义的实体一致
//使用FromSql
//执行表查询
var blogs = context.Blogs
.FromSql($"SELECT * FROM dbo.Blogs")
.ToList();
//执行存储过程查询返回实体
var blogs = context.Blogs
.FromSql($"EXECUTE dbo.GetMostPopularBlogs")
.ToList();
10.2. 标量查询(非实体)
场景:最终返回的结果为自定义结构,而非数据库实体
//使用SqlQuery
//执行查询,返回单个字段
var ids = context.Database
.SqlQuery<int>($"SELECT [BlogId] FROM [Blogs]")
.ToList();
//执行查询,返回自定义数据结构
var comments = context.Database
.SqlQuery<int>($"SELECT b.[BlogId],c.[CommnetContent] FROM [Blogs] b JOIN [Comments] c on b.BlogId = c.BlogId")
.ToList();
public class CustomBlog{
public int BlogId
public string CommnetContent
}
10.3. 执行非查询SQL
场景:提交更新,删除等操作,不关注返回结果
//使用ExecuteSql
//执行更新
context.Database.ExecuteSql($"UPDATE [Blogs] SET [Url] = NULL WHERE Id =1");
//执行删除
context.Database.ExecuteSql($"DELETE FROM [Blogs] WHERE Id =1");
10.3. SQL参数
//使用FromSql
//此代码无效,因为数据库不允许将列名(或架构的任何其他部分)参数化
var propertyName = "User";
var propertyValue = "johndoe";
var blogs = context.Blogs
.FromSql($"SELECT * FROM [Blogs] WHERE {propertyName} = {propertyValue}")
.ToList();
//正确姿势:使用 FromSqlRaw
var columnName = "Url";
var columnValue = new SqlParameter("columnValue", "http://SomeURL");
var blogs = context.Blogs
.FromSqlRaw($"SELECT * FROM [Blogs] WHERE {columnName} = @columnValue", columnValue)
.ToList();
其他关联性优化
除了针对EFCore本身的一些优化技巧之外,还有一些技巧可以帮助我们提升数据查询的效率,我们可以利用vs的调试工具帮助我们监听内存使用,CPU占用率等指标,查找瓶颈,总结主要从以下几个方面进行优化
- 尽量避免循环内查询,分析实际的业务逻辑,尽可能的一次性从数据库加载所有需要的数据,再进行循环处理
- 分片处理条件数据,例如使用Chunk,使用流式处理大批量的数据集的运算
- 使用合理的数据结构,例如在不关注数据顺序的场景下使用Dictionary或HashSet代替List等
- 使用缓存减少热点数据的访问(按需设计)
- 使用数据表索引及物化视图(数据库)
- 采用分库分表,读写分离,使用ES进行检索(架构级优化)
- 利用多线程并发提升效率(不到万不得已,慎用)
总结
EFCore的优化主要是从几个方面来进行:
1.减少数据库的交互,通过连接复用,上下文缓存等
2.减少内存的使用,例如使用流式处理,分页查询等
3.降低查询复杂度,尽量在程序中处理复杂的逻辑
保持良好的编码习惯,使用正确的数据结构和处理逻辑,优化应该是渐进式的,先正确的满足需求,在遇到性能问题的时候借助代码或工具去分析瓶颈,再去进行针对性的优化,不要为了优化而牺牲需求和浪费工作量。
最后留给大家一段问题代码示例,感兴趣的童鞋可以尝试利用上述手段优化这段代码,看看效率提升有多少:
var configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddUserSecrets<Program>()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
var serviceProvider = new ServiceCollection()
.AddDbContext<YouContext>(options =>
options.UseSqlServer(configuration["ConnectionStrings:YourContext"])
.EnableSensitiveDataLogging()
.UseLoggerFactory(LoggerFactory.Create(builder =>
{
builder.AddConsole().AddFilter((category, level) => category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information);
})))
.BuildServiceProvider();
using (var scope = serviceProvider.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<YourContext>();
context.Database.SetCommandTimeout(999);
var data = context.RELATIONSHIP.Where(x => x.workflow_state == 3).OrderBy(it => it.relationship_guid).Take(100000).ToList();
var tempData = data.Select(it => new Temp { aId = it.entity_from_guid, bId = it.entity_to_guid, deg = 0 }).ToList();
foreach (var item in tempData)
{
item.deg = GetInterConnectResult(item.aId, item.bId);
}
int GetInterConnectResult(Guid aId, Guid bId)
{
HashSet<Bo> boData = new();
for (int i = 1; i <= 3; i++)
{
if (boData.Any(it => it.guid == bId)) break;
var addIds = boData.Where(it => it.deg == i - 1).Select(it => it.guid).Distinct().ToList();
var addRelationships = context.Table1.Where(it => addIds.Contains(it.aid) || addIds.Contains(it.bid));
var addDegEntities = addRelationships.Select(it => new
{
efguid = it.aid,
etguid = it.bid
}).Union(addRelationships.Select(it => new
{
efguid = it.bid,
etguid = it.aid
}))
.Select(it => new Bo { guid = it.etguid, deg = i })
.ToHashSet() ?? new();
boData.UnionWith(addDegEntities ?? new());
}
return boData?.OrderByDescending(it => it.deg)?.FirstOrDefault(it => it.guid.Equals(bId))?.deg ?? 0;
}
}
作者:百宝门-周志飞
EF Core性能优化技巧的更多相关文章
- C#实用杂记-EF全性能优化技巧
原文链接:http://www.makmong.com/947.html#comment-31 EntityFramework 优化建议 2016年1月15日 下午4:54 LEILINKANG ...
- EF Core性能优化(一)
跟踪查询 返回实体类型的查询是默认会被跟踪的. 这表示可以更改这些实体实例,然后通过 SaveChanges() 持久化这些更改.非跟踪查询 在只读方案中使用结果时,非跟踪查询十分有用. 可以更快速地 ...
- C#实用杂记-EF全性能优化技巧2
原文链接: http://www.cnblogs.com/zhaopei/p/5721789.html
- Python代码性能优化技巧
摘要:代码优化能够让程序运行更快,可以提高程序的执行效率等,对于一名软件开发人员来说,如何优化代码,从哪里入手进行优化?这些都是他们十分关心的问题.本文着重讲了如何优化Python代码,看完一定会让你 ...
- Python 代码性能优化技巧(转)
原文:Python 代码性能优化技巧 Python 代码优化常见技巧 代码优化能够让程序运行更快,它是在不改变程序运行结果的情况下使得程序的运行效率更高,根据 80/20 原则,实现程序的重构.优化. ...
- Python 代码性能优化技巧
选择了脚本语言就要忍受其速度,这句话在某种程度上说明了 python 作为脚本的一个不足之处,那就是执行效率和性能不够理想,特别是在 performance 较差的机器上,因此有必要进行一定的代码优化 ...
- 轻量级HTTP服务器Nginx(Nginx性能优化技巧)
轻量级HTTP服务器Nginx(Nginx性能优化技巧) 文章来源于南非蚂蚁 一.编译安装过程优化 1.减小Nginx编译后的文件大小在编译Nginx时,默认以debug模式进行,而在debu ...
- Java程序性能优化技巧
Java程序性能优化技巧 多线程.集合.网络编程.内存优化.缓冲..spring.设计模式.软件工程.编程思想 1.生成对象时,合理分配空间和大小new ArrayList(100); 2.优化for ...
- JavaScript 性能优化技巧分享
JavaScript 作为当前最为常见的直译式脚本语言,已经广泛应用于 Web 应用开发中.为了提高Web应用的性能,从 JavaScript 的性能优化方向入手,会是一个很好的选择. 本文从加载.上 ...
- Unity UI性能优化技巧
本文将介绍一些提升Unity UI性能的技巧.更多优化技巧,可以观看Unity工程师Ian Dundore在Unite Europe 2017的演讲<使用Unity性能提升技巧>. 1.划 ...
随机推荐
- Python保姆级教程 数据类型—新手小白入门必看系列
推荐使用压缩软件和杀毒软件 7 - zip 使用火绒 一.基本数据类型与变量(上) 2.1 注释 优点: 代码说明 没注释的代码 有注释的代码 不让解释器执行注释的那句话 2.2 单行注释 单行注释快 ...
- SpringBoot系列(二) 环境搭建,创建我的第一个程序HelloWord。
环境准备: jdk1.8:java version "1.8.0_231",详见链接 maven3.x:maven3.3以上版本,详见链接 IDEA2021:IntelliJ ID ...
- 让Easysearch运行在LoongArch(3C5000L)上
简介 在上一次,我介绍了在国产操作系统 Kylin V10 (Lance)-aarch64 上安装单机版 Easysearch/Console/Agent/Gateway/Loadgen,小伙伴们可查 ...
- 【 INFINI Workshop 上海站】7 月 27 日一起动手实验玩转 Easysearch
[ INFINI Workshop 上海站]7 月 27 日下午 和 INFINI Labs 的技术专家面对面,第一时间了解极限实验室的发布最新产品和功能特性,通过动手实战,快速掌握最前沿的搜索技术, ...
- Visual Studio 2022 community 社区版本离线安装
下载好 vs_community__115739266.1625310894.exe 的,重命名为:vs_community2022.exe 命令: E:\vs_community2022.exe - ...
- C#.NET rabbit mq 持久化时报错 durable
The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=406, text='PRECONDITI ...
- ChatGPT应用与实践初探
近期,长江商学院EMBA38期&甄知科技开展了题为"ChatGPT应用与实践初探"的线下沙龙活动,由上海甄知科技创始合伙人兼CTO张礼军主讲,主要给大家解密最近很火的Cha ...
- CNN -- Simple Residual Network
Smiling & Weeping ---- 我爱你,从这里一直到月亮,再绕回来 说明: 1.要解决的问题:梯度消失 2. 跳连接,H(x) = F(x)+x,张量维度必须一致,加完后再激活. ...
- ELKF(elasticsearch、logstash、kibana、filebeat)搭建及收集nginx日志
1.elasticsearch 1.1.根目录下新建data文件夹 1.2.修改elasticsearch.yml文件,添加以下内容 path.data: /home/wwq/elk/elastics ...
- Shell读取整行
像C/C++,JAVA,Python等语言中,可以轻松地对文件进行按行读取. 那么,Shell中怎么实现对行读取呢? #!/bin/bash while read i do echo $i done ...