使用“WHERE [tinyint] ORDER BY ID”的慢 MySQL 查询

Posted

技术标签:

【中文标题】使用“WHERE [tinyint] ORDER BY ID”的慢 MySQL 查询【英文标题】:Slow MySQL query with "WHERE [tinyint] ORDER BY ID" 【发布时间】: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 或内存不足、页面大小过小等。如果您可以确认索引存在并使用,那么我们可以缩小导致问题的范围。跨度> 【参考方案1】:

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

【讨论】:

【参考方案2】:

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

WHERE Blocked = 1
ORDER BY Id

一起

INDEX(Blocked, Id)

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

【讨论】:

以上是关于使用“WHERE [tinyint] ORDER BY ID”的慢 MySQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

第一篇 用于测试使用

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份