【发布时间】:2020-09-14 15:37:15
【问题描述】:
我的数据库用户和文章中有两个表。
我的用户和文章表中的记录如下:
+----+--------+
| id | name |
+----+--------+
| 1 | user1 |
| 2 | user2 |
| 3 | user3 |
+----+--------+
+----+---------+----------+
| id | user_id | article |
+----+---------+----------+
| 1 | 1 | article1 |
| 2 | 1 | article2 |
| 3 | 1 | article3 |
| 4 | 2 | article4 |
| 5 | 2 | article5 |
| 6 | 3 | article6 |
+----+---------+----------+
给出下面的查询和受人尊敬的EXPLAIN 输出。
EXPLAIN SELECT * FROM articles WHERE user_id = 1;
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | articles | NULL | ALL | user_id | NULL | NULL | NULL | 6 | 50.00 | Using where |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+
EXPLAIN SELECT * FROM articles WHERE user_id = 2;
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | articles | NULL | ref | user_id | user_id | 5 | const | 2 | 100.00 | NULL |
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------+
EXPLAIN SELECT * FROM articles WHERE user_id = 3;
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | articles | NULL | ref | user_id | user_id | 5 | const | 1 | 100.00 | NULL |
+----+-------------+----------+------------+------+---------------+---------+---------+-------+------+----------+-------+
查看我的选择查询的EXPLAIN 计划,查询似乎并不总是使用索引。
万一,
user_id为1时,不使用key,扫描全表。
否则,它使用user_id 键并且只扫描几行。
您能否解释一下为什么查询并不总是在这里使用索引?
【问题讨论】:
-
那是 mysql 优化器的领域。 dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html
In some cases, a query can be optimized to retrieve values without consulting the data rows.和文章底部Indexes are less important for queries on small tables, or big tables where report queries process most or all of the rows. -
您的表的行数太少,以至于使用索引最终可能比一次读取整个数据更昂贵。当您检索 1) 几行,2) 从大表中检索时,索引的性能非常好;您的示例中不满足第二个条件。
-
感谢您明确说明。我明白了。但我仍然对查询的不一致行为感到困惑。使用索引可能最终会更昂贵,那么为什么在 user_id 为 2 或 3 时使用索引进行查询?
-
因为它取决于值的选择性 - 如果 1 的
user_id比值 2 或 3 更常见,则优化器可能会认为值 1 具有较低的选择性,因此它将是最好进行全表扫描。此行为由在 INSERT/UPDATE/DELETE 期间收集的统计信息控制。看看这些文章dev.mysql.com/doc/refman/8.0/en/statistics-table.htmlpercona.com/blog/2017/09/11/… -
请提供
SHOW CREATE TABLE articles
标签: mysql database query-optimization sql-execution-plan explain