使用“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有三种方式(不使用,动态使用,静态使用,默认是动态使用)