MySQL 在使用 SELECT * 时不使用索引

问题描述 投票:0回答:1

我在向表添加新索引时遇到一些问题,我想知道为什么 MySQL 不使用新索引。

我注意到,只有当我的 SELECT 语句请求不属于索引的其他列时才会发生这种情况(例如

SELECT *
不起作用,而
SELECT id, otherId
起作用)。

有人可以向我解释一下为什么MySQL选择进行表扫描而不是使用索引吗?

数据库架构

该表由多列组成,即

id
otherId
id
是我的主键,而
otherId
也应该被索引。
otherId
可以为空并且是唯一的。

model Entity {
    id      String  @id @default(cuid())
    otherId String? @unique
    // Few more ...
}

基数和选择性

SELECT
  COUNT(DISTINCT Entity.otherId) as cardinality,
  COUNT(*) as totalRows,
  COUNT(Entity.otherId) as nonNullRows,
  COUNT(DISTINCT Entity.otherId) / COUNT(*) as selectivity
FROM
  Entity
基数 总行数 非空行 选择性
171 1187 171 0.1441

解释选择*

这个不使用索引,但我希望它会。

EXPLAIN SELECT * FROM Entity WHERE Entity.otherId = ?;
id 选择类型 桌子 分区 类型 可能的键 key_len 参考 过滤 额外
1 简单 实体 全部 Entity_otherId_key 1187 10 使用地点

解释选择 id, otherId

这个确实使用了索引。

EXPLAIN SELECT id, otherId FROM Entity WHERE Entity.otherId = ?;
id 选择类型 桌子 分区 类型 可能的键 key_len 参考 过滤 额外
1 简单 实体 索引 Entity_otherId_key Entity_otherId_key 767 1187 10 使用地点;使用索引

显示索引

SHOW INDEXES from Entity;
桌子 非唯一 密钥名称 索引中的序列 列_名称 整理 基数 子_部分 包装好 索引_类型 评论 索引_评论 可见 表情
实体 0 小学 1 id A 1187 BTREE
实体 0 Entity_otherId_key 1 其他ID A 172 BTREE

MySQL版本

8.2.0

sql mysql database performance query-optimization
1个回答
0
投票

您的查询均不执行任何行限制(WHERE 子句)或排序(ORDER BY 子句)。所以他们必须检查每一行。

这得到了两个 EXPLAIN 结果的

rows
列的支持。两者都显示 1187。

但是

type: ALL
type: index
有什么区别?

第一个是表扫描。该查询将检查表中的每一行。由于 MVCC,它必须这样做才能对它们进行计数。因此查询的成本与行数成正比。

第二个是索引扫描。这比表扫描稍好一些,但它仍然需要检查命名索引中的每个条目来对它们进行计数。成本也与行数成正比,但它可能能够检查更少的页面来单独读取索引而不是整个表。

解释“使用索引”中的注释让您相信它已经优化了。严格来说,它确实为此查询使用了索引,但它使用索引的方式与搜索或排序不同。

© www.soinside.com 2019 - 2024. All rights reserved.