EF Core 使用编译查询提高性能
2018-01-15 07:38
295 查看
今天,我将向您展示这些EF Core中一个很酷的功能,通过使用显式编译的查询,提高查询性能。
不过在介绍具体内容之前,需要说明一点,EF Core已经对表达式的编译使用了缓存;当您的代码需要重用以前执行的查询时,EF Core将使用哈希查找并从缓存中返回已编译的查询。
不过,您可能希望直接对查询进行编译,跳过哈希的计算和缓存查找。我们可以通过在
EF.CompileQuery()
EF.CompileAsyncQuery()
这些方法允许您定义一个已编译的查询,然后通过调用一个委托调用它。
为了避免因为数据库查询产生测试结果的差异,我们这里使用内存数据库,它开销更小,同时也可以避免数据库优化执行计划以及缓存所带来的问题。
在这我们定义一个
数据库DbContext
在
为了更加接近测试结果,我们在构造函数中创建
经过编译的查询比未编译过的查询存在接近8倍的差距。如果您对这个功能感兴趣,不防自己测试一下。
不过在介绍具体内容之前,需要说明一点,EF Core已经对表达式的编译使用了缓存;当您的代码需要重用以前执行的查询时,EF Core将使用哈希查找并从缓存中返回已编译的查询。
不过,您可能希望直接对查询进行编译,跳过哈希的计算和缓存查找。我们可以通过在
EF静态类中下面两个方法来实现:
EF.CompileQuery()
EF.CompileAsyncQuery()
这些方法允许您定义一个已编译的查询,然后通过调用一个委托调用它。
为了避免因为数据库查询产生测试结果的差异,我们这里使用内存数据库,它开销更小,同时也可以避免数据库优化执行计划以及缓存所带来的问题。
实体定义以前数据库DbContext
定义实体在这我们定义一个
Category实体类型,非常简单,只有两个属性。
public class Category { public Guid Id { get; set; } public string Name { get; set; } }
数据库DbContext
在
FillCategories方法中,将内存数据库中增加三条记录。
public class TestDbContext : DbContext { public TestDbContext(DbContextOptions<TestDbContext> options) : base(options) { } public DbSet<Category> Categories { get; set; } public void FillCategories() { var foodCategory = new Category { Id = Guid.NewGuid(), Name = "Food" }; Categories.AddRange(foodCategory, new Category { Id = Guid.NewGuid(), Name = "Drinks" }, new Category { Id = Guid.NewGuid(), Name = "Clothing" }, new Category { Id = Guid.NewGuid(), Name = "Electronis" }); SaveChanges(true); } }
测试代码
public class CompileQueryTest { private Func<TestDbContext, Guid, Category> _getCategory = EF.CompileQuery((TestDbContext context, Guid id) => context.Categories.FirstOrDefault(c => c.Id == id)); private readonly TestDbContext _dbContext; public CompileQueryTest() { var options = new DbContextOptionsBuilder<TestDbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options; var context = new TestDbContext(options); context.FillCategories(); _dbContext = context; } private readonly Guid _queryId = Guid.NewGuid(); [Benchmark] public void CompiledQuery() { _ = _getCategory(_dbContext, _queryId); } [Benchmark] public void UnCompiledQuery() { _ = _dbContext.Categories.FirstOrDefault(c => c.Id == _queryId); } }
为了更加接近测试结果,我们在构造函数中创建
TestDbContext对象以及填充数据库。
测试结果
我们使用Benchmark.Net进行基准测试,测试结果如下:Method | Mean | Error | StdDev |
---|---|---|---|
CompiledQuery | 10.59 us | 0.0580 us | 0.0543 us |
UnCompiledQuery | 79.55 us | 0.7860 us | 0.7353 us |
相关文章推荐
- Oracle模糊查询之(3.2从使用函数和sql语法角度来提高模糊查询效率 二)ORACLE中Like与Instr模糊查询性能大比拼
- 使用计算列提高查询性能
- 使用各种查询选择来提高性能
- LINQ – 使用DataLoadOptions 提高LINQ to SQL 查询性能
- 使用正确的筛选参数来提高查询性能
- CTE和WITH AS短语结合使用提高SQL查询性能
- 使用正确的筛选参数来提高查询性能
- 使用查询改写提高查询性能
- 使用Filtered Indexes提高查询性能
- 性能优化(一个)Hibernate 使用缓存(一个、两、查询)提高系统性能
- 使用PreparedStatement 防止SQL攻击 实现预编译功能提高性能
- 使用索引不一定能提高查询性能
- 使用索引和统计特性来提高数据库的查询性能(转)
- 使用索引查询是否能提高查询的性能以及索引的优缺点
- 使用正确的筛选参数来提高查询性能
- 提高sql查询性能-使用instr函数替换like
- CTE和WITH AS短语结合使用提高SQL查询性能
- 使用VO和EO的AlternateKey特性提高查询性能
- 使用查询改写提高查询性能
- 使用游标批量获取数据提高查询性能