首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EF Core 3.1查询优化

EF Core 3.1查询优化
EN

Stack Overflow用户
提问于 2020-02-03 16:37:09
回答 1查看 730关注 0票数 2

我经常听说,EF Core 3.1现在能够优化分组和几个聚合函数,如在数据库上执行的sum。为什么我的C#代码会将这种严重未经优化的代码发送到数据库服务器?

代码语言:javascript
复制
using var dbContext = new DatabaseContext();
var someTableData = await dbContext.SomeTable
    .GroupBy(x => x.Foobar)
    .Select(x => new { Foobar = x.Key, Quantity = x.Sum(y => y.Quantity) })
    .OrderByDescending(x => x.Quantity)
    .Take(10)
    .ToListAsync();

SQL (从实体框架日志复制):

代码语言:javascript
复制
SELECT [...] FROM public."SomeTable"

正如您所看到的:查询不包含任何排序、分组、汇总……

我通过创建一个视图解决了我的问题,因为原始的ef核心查询将应用程序的RAM使用量增加了2 2GB (在2秒内),因为有很多表项。但我的问题仍然是:我做错了什么?是不是因为我用的是PostgreSQL (Npgsql.EntityFrameworkCore.PostgreSQL v3.1.0)?

EN

回答 1

Stack Overflow用户

发布于 2020-02-03 18:09:26

我将您的查询弹出到一个快速测试工具中(请参阅下面所有nuget包版本的项目定义):

代码语言:javascript
复制
public class SomeTable
{
    public int Id { get; set; }
    public int Foobar { get; set; }
    public int Quantity { get; set; }
}

class MyDbContext : DbContext
{
    public DbSet<SomeTable> SomeTables { get; set; }
    public static readonly LoggerFactory DbCommandConsoleLoggerFactory
        = new LoggerFactory(new[] {
            new ConsoleLoggerProvider ((category, level) =>
                category == DbLoggerCategory.Database.Command.Name &&
                level == LogLevel.Trace, true)
        });
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseNpgsql("Server=...;Port=5432;Database=test;User Id=...;Password=...;")
        //optionsBuilder.UseSqlServer("Server=.\\SQLEXPRESS;Database=test;Trusted_Connection=true")
                    .UseLoggerFactory(DbCommandConsoleLoggerFactory)
                    .EnableSensitiveDataLogging();
        base.OnConfiguring(optionsBuilder);
    } 
}

class Program
{
    static void Main(string[] args)
    {
        var context = new MyDbContext();
        var someTableData = context.SomeTables
                .GroupBy(x => x.Foobar)
                .Select(x => new { Foobar = x.Key, Quantity = x.Sum(y => y.Quantity) })
                .OrderByDescending(x => x.Quantity)
                .Take(10);
        Console.Write(someTableData);
        Console.ReadKey();
    }
}
/*csproj file contents below:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <RootNamespace>ef_core3_playground</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.0" />
    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.1" />
  </ItemGroup>

</Project>
*/

我最终为各自的提供程序获得了以下SQL:

代码语言:javascript
复制
--MS SQL
SELECT TOP(@__p_0) [s].[Foobar], SUM([s].[Quantity]) AS [Quantity]
FROM [SomeTables] AS [s]
GROUP BY [s].[Foobar]
ORDER BY SUM([s].[Quantity]) DESC

-- PG SQL
SELECT s."Foobar", SUM(s."Quantity")::INT AS "Quantity"
FROM "SomeTables" AS s
GROUP BY s."Foobar"
ORDER BY SUM(s."Quantity")::INT DESC
LIMIT @__p_0

这让我想知道是不是你的提供商/EF特定的版本给了你这样的结果?虽然在diff between two npgsql releases中我看不到任何与这个问题相关的东西,但我建议您尝试将所有与EF相关的包升级到3.1.1并重复您的测试。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60035640

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档