4
EXPLAIN SELECT
*
FROM
content_link link
STRAIGHT_JOIN
content
ON
link.content_id = content.id
WHERE
link.content_id = 1
LIMIT 10;

+----+-------------+---------+-------+---------------+------------+---------+-------+------+-------+
| id | select_type | table   | type  | possible_keys | key        | key_len | ref   | rows | Extra |
+----+-------------+---------+-------+---------------+------------+---------+-------+------+-------+
|  1 | SIMPLE      | link    | ref   | content_id    | content_id | 4       | const |    1 |       |
|  1 | SIMPLE      | content | const | PRIMARY       | PRIMARY    | 4       | const |    1 |       |
+----+-------------+---------+-------+---------------+------------+---------+-------+------+-------+

但是,当我删除 WHERE 时,查询会停止使用该键(即使我明确强制它使用)

EXPLAIN SELECT
*
FROM
content_link link FORCE KEY (content_id)
STRAIGHT_JOIN
content
ON
link.content_id = content.id
LIMIT 10;

+----+-------------+---------+--------+---------------+---------+---------+------------------------+---------+-------------+
| id | select_type | table   | type   | possible_keys | key     | key_len | ref                    | rows    | Extra       |
+----+-------------+---------+--------+---------------+---------+---------+------------------------+---------+-------------+
|  1 | SIMPLE      | link    | index  | content_id    | PRIMARY | 7       | NULL                   | 4555299 | Using index |
|  1 | SIMPLE      | content | eq_ref | PRIMARY       | PRIMARY | 4       | ft_dir.link.content_id |       1 |             |
+----+-------------+---------+--------+---------------+---------+---------+------------------------+---------+-------------+

有什么解决方法吗?

我意识到我在第二个示例中选择了整个表,但是为什么 mysql 突然决定它无论如何都会忽略我的 FORCE 并且不使用密钥?如果没有密钥,查询大约需要 10 分钟.. 呃。

4

3 回答 3

4

FORCE 有点用词不当。这是 MySQL 文档所说的(强调我的):

您还可以使用 FORCE INDEX,它的作用类似于 USE INDEX (index_list),但另外假设表扫描非常昂贵。换句话说,仅当无法使用给定索引之一来查找表中的行时,才使用表扫描。

由于您实际上并没有“找到”任何行(您正在选择所有行),因此表扫描总是最快的,并且优化器足够聪明,可以知道尽管您告诉他们什么。

预计到达时间:

尝试在主键上添加一次 ORDER BY,我敢打赌它会使用索引。

于 2009-06-03T17:21:08.470 回答
4

索引有助于在表内快速搜索,但如果您选择整个表,它只会减慢速度。所以 MySQL 忽略索引是正确的。

在您的情况下,索引可能具有 MySQL 不知道的隐藏副作用。例如,如果内连接只保留几行,则索引会加快速度。但是如果没有明确的提示,MySQL 是无法知道的。

有一个例外:当您选择的每一列都在索引内时,如果您选择每一行,索引仍然有用。例如,如果您在 LastName 上有一个索引,则以下查询仍然受益于该索引:

select LastName from orders

但是这个不会:

select * from Orders
于 2009-06-03T17:13:49.617 回答
0

content_id似乎接受NULL价值观。

MySQL优化器认为不能保证您的查询将仅通过使用索引返回所有值(尽管实际上有保证,因为您使用 a 中的列JOIN

这就是它恢复为全表扫描的原因。

添加NOT NULL条件:

SELECT  *
FROM    content_link link FORCE KEY (content_id)
STRAIGHT_JOIN
        content
ON      content.id = link.content_id
WHERE   link.content_id IS NOT NULL
LIMIT 10;

或将您的列标记为NOT NULL

ALTER TABLE content_link MODIFY content_id NOT NULL

更新:

这是已验证的错误 45314MySQL.

于 2009-06-03T17:31:42.527 回答