为什么这个实体框架查询在 MySQL 中表现如此糟糕?

Nic*_*rdi 6 mysql performance orm entity-framework

让我给你一些设置。我们在 MySQL 5.1 上有一个 InnoDB 表,有近 2000 万条记录,没有外键,以及我们所做的查询的适当索引。我们正在为 .NET Entity Framework 使用最新的 6.3.5 MySQL 版本。通常我们习惯于处理 SQL Server 和实体框架,但在这个项目中我们决定尝试一下 MySQL。

我对这个问题有一些理论,但让我先做代码设置

EF LINQ 查询

var failsForAcct1001 = db.Failures.Where(x => x.AccountId == 1001);
/* farther down and later on in the code */
return failsForAcct1001.OrderBy(x => x.FailureId).Take(50);
Run Code Online (Sandbox Code Playgroud)

生成的 MySQL 代码

请忽略列名,它们不是理解问题所必需的

select
    External1.FailureId,
    External1.col2,
    External1.col3,
from (select
          Inner1.FailureId,
          Inner1.col2,
          Inner1.col3,
      from Failures Inner1
      where External1.AccountId = 1001
    ) External1
order by External1.FailureId
limit 50
Run Code Online (Sandbox Code Playgroud)

生成的这个 SQL 与 SQL Server 中发生的情况非常相似,SQL 处理它没有问题。这不仅仅是一个实体框架问题,当我接受这个查询并在 MySQL Workbench 中执行时,它也会超时。但是,以下查询会在不到半秒的时间内返回。

select
    External1.FailureId,
    External1.col2,
    External1.col3,
from Failures External1
where External1.AccountId = 1001
order by External1.FailureId
limit 50
Run Code Online (Sandbox Code Playgroud)

我认为这个性能问题与 MySQL 正在尝试执行内部查询有关,该查询拉回数据库中的所有记录,然后尝试排序并取 50,而不是像第二个查询那样将所有这些作为一个操作执行做。

我真的只是想确认我的观察,并询问我是否可以做任何事情来使第一个 SQL 语句更快地执行,而无需以任何方式修改查询。

Gai*_*ius 5

第 1 步 - 获取解释计划,特别是EXPLAIN EXTENDED将向您展示查询优化器实际生成的 SQL。也许额外的索引会有所帮助 - 但如果你“外包”你的 SQL 生成,那么你真的会受制于对 ORM 开发人员来说更容易的东西,而不是最适合你的应用程序的东西。您可以尝试的另一件事是in-memory temp db,因为这可以帮助排序和派生表,您确实拥有...