仅查询索引字段时在 EXPLAIN 的额外列中获取 "Using where; Using index"

Getting "Using where; Using index" in Extra column of EXPLAIN when only querying indexed fields

当运行以下查询时:

EXPLAIN SELECT 
    belgarath.match_oc_history.id_, belgarath.match_oc_history.tour_id
FROM
    belgarath.match_oc_history
        JOIN
    belgarath.tournament_oc ON belgarath.tournament_oc.tour_id = belgarath.match_oc_history.tour_id
        AND belgarath.tournament_oc.orig_id = belgarath.match_oc_history.tournament_oc_orig_id;

我得到以下 table:

+----+-------------+------------------+------------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------+---------+-----------------------------------------------------------------+-------+----------+--------------------------+
| id | select_type |      table       | partitions | type  |                                                                                          possible_keys                                                                                           |                         key                          | key_len |                               ref                               | rows  | filtered |          Extra           |
+----+-------------+------------------+------------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------+---------+-----------------------------------------------------------------+-------+----------+--------------------------+
|  1 | SIMPLE      | tournament_oc    | NULL       | index | uq__tournament_oc__tour_id__orig_id,ix__tournament_oc__tour_id,ix__tournament_oc__orig_id                                                                                                        | uq__tournament_oc__tour_id__orig_id                  |       6 | NULL                                                            | 26550 |      100 | Using where; Using index |
|  1 | SIMPLE      | match_oc_history | NULL       | ref   | ix__match_oc_history__five_keys,ix__match_oc_history__tour_id,fk__match_oc_history__player_oc_p1_idx,fk__match_oc_history__player_oc_p2_idx,fk__match_oc_history__tour_id__tournament_oc_orig_id | fk__match_oc_history__tour_id__tournament_oc_orig_id |       5 | belgarath.tournament_oc.tour_id,belgarath.tournament_oc.orig_id |    54 |      100 | Using index              |
+----+-------------+------------------+------------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------+---------+-----------------------------------------------------------------+-------+----------+--------------------------+

我从周围阅读的理解是,如果查询只使用索引字段,那么它不需要使用 where。这是正确的吗?

如果是,那为什么我会在 EXPLAIN table 中看到它弹出?

如果不是,我应该担心在这种情况下使用 where 吗?我一直认为 whereindex...

Table 作文:

CREATE TABLE `tournament_oc` (
  `updated` timestamp NULL DEFAULT NULL,
  `created` timestamp NULL DEFAULT NULL,
  `id_` int NOT NULL AUTO_INCREMENT,
  `tour_id` tinyint DEFAULT NULL,
  `orig_id` int NOT NULL,
  PRIMARY KEY (`id_`),
  UNIQUE KEY `uq__tournament_oc__tour_id__orig_id` (`tour_id`,`orig_id`),
  KEY `ix__tournament_oc__tour_id` (`tour_id`),
  KEY `ix__tournament_oc__orig_id` (`orig_id`),
  CONSTRAINT `fk__tournament_oc__tour_id` FOREIGN KEY (`tour_id`) REFERENCES `tour` (`id_`)
) ENGINE=InnoDB AUTO_INCREMENT=27788 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci


CREATE TABLE `match_oc_history` (
  `updated` timestamp NULL DEFAULT NULL,
  `created` timestamp NULL DEFAULT NULL,
  `id_` int NOT NULL AUTO_INCREMENT,
  `tour_id` tinyint NOT NULL,
  `tournament_oc_orig_id` int NOT NULL,
  `round_oc_id` tinyint NOT NULL,
  `player_oc_orig_id_p1` int NOT NULL,
  `player_oc_orig_id_p2` int NOT NULL,
  PRIMARY KEY (`id_`),
  KEY `ix__match_oc_history__five_keys` (`tour_id`,`tournament_oc_orig_id`,`round_oc_id`,`player_oc_orig_id_p1`,`player_oc_orig_id_p2`),
  KEY `ix__match_oc_history__round_oc_id` (`round_oc_id`),
  KEY `ix__match_oc_history__tour_id` (`tour_id`),
  KEY `fk__match_oc_history__player_oc_p1_idx` (`tour_id`,`player_oc_orig_id_p1`),
  KEY `fk__match_oc_history__player_oc_p2_idx` (`tour_id`,`player_oc_orig_id_p2`),
  KEY `fk__match_oc_history__tour_id__tournament_oc_orig_id` (`tour_id`,`tournament_oc_orig_id`),
  CONSTRAINT `fk__match_oc_history__player_oc_p1` FOREIGN KEY (`tour_id`, `player_oc_orig_id_p1`) REFERENCES `player_oc` (`tour_id`, `orig_id`),
  CONSTRAINT `fk__match_oc_history__player_oc_p2` FOREIGN KEY (`tour_id`, `player_oc_orig_id_p2`) REFERENCES `player_oc` (`tour_id`, `orig_id`),
  CONSTRAINT `fk__match_oc_history__round_oc_id` FOREIGN KEY (`round_oc_id`) REFERENCES `round_oc` (`id_`),
  CONSTRAINT `fk__match_oc_history__tour_id` FOREIGN KEY (`tour_id`) REFERENCES `tour` (`id_`),
  CONSTRAINT `fk__match_oc_history__tournament_oc` FOREIGN KEY (`tour_id`, `tournament_oc_orig_id`) REFERENCES `tournament_oc` (`tour_id`, `orig_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1516084 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

根据评论:

SHOW WARNINGS 语句响应:

/* select#1 */ select `belgarath`.`match_oc_history`.`id_` AS `id_`,`belgarath`.`match_oc_history`.`tour_id` AS `tour_id` from `belgarath`.`match_oc_history` join `belgarath`.`tournament_oc` where ((`belgarath`.`match_oc_history`.`tournament_oc_orig_id` = `belgarath`.`tournament_oc`.`orig_id`) and (`belgarath`.`match_oc_history`.`tour_id` = `belgarath`.`tournament_oc`.`tour_id`))
  • Using index 意味着整个查询(至少对于有问题的 table)不需要除 INDEX 中的任何列。这比必须在索引的 BTree 和数据的 BTree 之间来回跳动要快。
  • 优化器可以自由地重新排序 JOINed table,因为它认为合适。 EXPLAIN 反映了优化器的决定。
  • “警告”显示了它如何决定执行查询。
  • OR在解析的时候经常会变成WHERE。 (您使用 ON 是正确的,因为这就是 table 的关联方式。)
  • 没有真正的 WHERE,优化器 [通常] 选择较小的 table,然后执行“嵌套循环连接”(NLJ) 以进入下一个 table。这通常是执行查询的更快方法。我认为不需要 STRAIGHT_JOIN;相信优化器。
  • 您拥有最佳复合索引,可以让优化器首先选择 table 中的一个。
  • 你认为 'wrong' table 为什么先?
  • “Using where”意义不大;忽略它。
  • “where is slower than index”——这没有意义。带有 suitable 索引的 WHERE 子句 将使查询 运行 更快。 ON 子句几乎总是需要一个索引来 运行 更快。 (你所拥有的实际上是 ON。)