【问题标题】:Slow MySQL query with "WHERE [tinyint] ORDER BY ID"使用“WHERE [tinyint] ORDER BY ID”的慢 MySQL 查询
【发布时间】:2021-07-16 09:33:43
【问题描述】:

我有一个表,其中包含一个类似于布尔值的字段“阻塞”(作为不可为空的 tinyint),我有一个索引。

跑步

  SELECT `p`.`Id`
  FROM `ProjectTasks` AS `p`
  WHERE `p`.`Blocked` > 0
  ORDER BY `p`.`Id`

  SELECT `p`.`Id`
  FROM `ProjectTasks` AS `p`
  WHERE `p`.`Blocked`

都很快(MySql Workbench 显示 0.000 秒)。

但正在运行

  SELECT `p`.`Id`
  FROM `ProjectTasks` AS `p`
  WHERE `p`.`Blocked`
  ORDER BY `p`.`Id`

非常慢(返回 50.000 个条目中的约 50 个时需要 0.5 秒)。

使用 EXPLAIN 表示后面的查询没有用到 Index。

不幸的是,我不能只添加> 0,因为查询是由 EF Core 生成的。我可以对索引进行任何更改,以便将其与最新版本的查询一起使用吗?

【问题讨论】:

  • 您实际上可以告诉 EF Core 为您定义选定列的索引,这将确保您的查询在查询某些列时使用索引。看看文档。 docs.microsoft.com/en-us/ef/core/modeling/…
  • 通过(Blocked, Id)创建一个索引并使用WHERE `p`.`Blocked` = 1 ORDER BY `p`.`Id` (如果它是“boolean-like NOT NULL”那么它的值只有0和1)。
  • @MaulikParmar 我已经有modelBuilder.Entity<ProjectTask>().HasIndex(pt => new { pt.Blocked });(并且刚刚添加了另一个带有 Blocked,Id 的索引),但它没有被使用。 @Akina 我已经添加了索引,但是 WHERE p.Blocked 没有使用它。我无法添加= 1,因为查询是由 EF Core 生成的。
  • protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<ProjectTask>() .HasIndex(pt => new { pt.id, pt.Blocked }); } 你能确认你的数据库已经定义了索引吗?如果不只是迁移模型,请重新创建以便它实际创建索引。索引在创建表或迁移的同时创建。确保它在那里,mysql也支持布尔类型,为什么不使用它应该没有问题。
  • 查询速度慢可能有多种原因,可能是 io 或内存不足、页面大小过小等。如果您可以确认索引存在并使用,那么我们可以缩小导致问题的范围。跨度>

标签: mysql performance entity-framework-core


【解决方案1】:

ORDER BY 子句也可以从使用索引中受益匪浅。您的 p.Id 字段是否已编入索引?如果没有,我建议您在 p.Id 上创建一个索引。

【讨论】:

    【解决方案2】:

    如果 EF Core 无法生成所需的 SQL,它是否至少允许您编写“原始”SQL?如果两者都不是,则抛弃框架;碍事了。

    WHERE Blocked = 1
    ORDER BY Id
    

    一起

    INDEX(Blocked, Id)
    

    可以被 MySQL 优化。几乎任何其他查询和索引都不能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-15
      • 1970-01-01
      • 2012-04-05
      • 2021-04-22
      • 1970-01-01
      • 2010-10-27
      相关资源
      最近更新 更多