查询有 67156 行的索引 MySQL 表,检查 162880 行,索引不起作用吗?

Posted

技术标签:

【中文标题】查询有 67156 行的索引 MySQL 表,检查 162880 行,索引不起作用吗?【英文标题】:Querying an indexed MySQL table with 67156 Rows, checks 162880 Rows, Does index not work? 【发布时间】:2020-03-22 21:40:38 【问题描述】:

我在我的数据库中查询wp_posts 表。

目前的指标如下:

我运行以下查询:

SELECT MIN(post_parent) 
FROM wp_posts 
WHERE  post_type = 'product_variation' and post_parent > 365191;

它检查 162880 行,如下所示:

但是,以下查询仅返回 67156 行。

SELECT COUNT(*) 
FROM wp_posts 
WHERE  post_type = 'product_variation' and post_parent > 365191;

那么为什么我的索引没有像我预期的那样工作?

PS: post_parent 是bigInt

【问题讨论】:

【参考方案1】:

您的索引正在“工作”,但对这个查询没有用处。

基本上,索引的一个目的是减少需要读取的数据页数。当查询读取 162,880 行中的 67,156 行时,优化器认为每个数据页都需要读取无论如何。那么,为什么还要使用索引呢。

注意,对于这个查询:

SELECT MIN(post_parent)
FROM wp_posts
WHERE post_type = 'product_variation' and post_parent > 365191;

最佳索引位于wp_posts(post_type, post_parent)。我猜这个索引实际上会被使用,因为它是查询的覆盖索引。所以读取索引比读取原始数据页更有优势。

【讨论】:

【参考方案2】:

您的索引正在“工作”,但它仅部分对此查询有用。

您没有透露type_status_date 索引的确切细节,但根据名称,我假设它按特定顺序索引帖子类型、帖子状态和帖子日期字段。

这意味着type_status_date 只能用于根据帖子类型缩小结果范围,但不能用于查找帖子父级,因为后者字段不是索引的一部分。 mysql 在一个查询中只能对一个表使用一个索引。

如果你执行了一个

SELECT COUNT(*) 
FROM wp_posts 
WHERE  post_type = 'product_variation'

查询,那么计数可能会更接近解释中扫描的行数。

正如 Gordon 解释的那样,在这种情况下,帖子类型、帖子父字段的索引会更有效。

【讨论】:

【参考方案3】: EXPLAIN 中的“行”是一个近似值;有时很遥远。 INDEX(post_type, post_parent) 不仅是“覆盖”(意味着在索引中找到所有必要的列),而且与 MIN() 一起,它只会查看一行来给出答案。 解释将通过说“使用索引”(而不是“使用索引条件”)来表示“覆盖”。 EXPLAIN 并不总是降低“行”以解释 LIMITMIN 等。所以,同样,你不能总是相信它。请参阅此以获得准确的计数:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#handler_counts

【讨论】:

以上是关于查询有 67156 行的索引 MySQL 表,检查 162880 行,索引不起作用吗?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL:子查询检查超过 14000 行的子查询优化问题

如何在不使用索引检查 mysql 表中的 100000 条记录等所有行的情况下获得一行? [关闭]

mysql 为表添加索引

深入理解MySQL索引原理和实现——为什么索引可以加速查询?

mysql创建删除查看索引

sql 10多万行的数据 求助