Mysql索引被忽略

Mysql索引被忽略,sql,mysql,indexing,primary-key,key,Sql,Mysql,Indexing,Primary Key,Key,但是,当我删除WHERE时,查询将停止使用该键(即使我显式强制它) 有什么解决办法吗 我意识到在第二个示例中我选择了整个表,但是为什么mysql突然决定不管怎样都忽略我的强制,而不使用键呢?如果没有密钥,查询大约需要10分钟。。啊。索引有助于在表内快速搜索,但如果选择整个表,它只会减慢搜索速度。所以MySQL忽略索引是正确的 在您的例子中,可能索引有一个MySQL不知道的隐藏副作用。例如,如果内部联接仅适用于几行,则索引将加快速度。但是如果没有明确的提示,MySQL无法知道这一点 有一个例外:当

但是,当我删除WHERE时,查询将停止使用该键(即使我显式强制它)

有什么解决办法吗


我意识到在第二个示例中我选择了整个表,但是为什么mysql突然决定不管怎样都忽略我的强制,而不使用键呢?如果没有密钥,查询大约需要10分钟。。啊。

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

在您的例子中,可能索引有一个MySQL不知道的隐藏副作用。例如,如果内部联接仅适用于几行,则索引将加快速度。但是如果没有明确的提示,MySQL无法知道这一点

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

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 |             |
+----+-------------+---------+--------+---------------+---------+---------+------------------------+---------+-------------+
但这个不会:

select LastName from orders

武力有点用词不当。以下是MySQL文档所说的(我的重点):

您还可以使用强制索引,其作用类似于使用索引(INDEX_list),但另外,表扫描被认为是非常昂贵的。换句话说,只有在无法使用给定索引之一查找表中的行时才使用表扫描

由于您实际上没有“查找”任何行(您选择了所有行),因此表扫描总是会以最快的速度进行,而且优化器非常聪明,无论您告诉他们什么,都会知道这一点

预计到达时间:


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

您的
内容id
似乎接受
空值

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

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

添加
非空
条件:

select * from Orders
或者将您的列标记为
非空

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;
更新:


这在
MySQL

中得到了验证,但我实际上并没有选择整个表。我对real query.Hmmm应用了一个LIMIT 10,那么MySQL在决定如何执行查询时可能没有考虑LIMIT子句。我知道如果使用TOP,Sql Server会更改其执行计划。LIMIT 10只会将结果集限制为10。它仍然必须执行查询,直到达到极限。由于给定的查询不要求数据限制(no WHERE子句),因此它将使用表扫描方法运行查询。若MySQL和SQL Server类似的话,那个么这将是非常昂贵的—将整个表读入临时存储,然后逐行检查临时数据。即使在完成临时表扫描之前,LIMIT语句也可能不会得到遵守。在执行查询时,LIMIT确实适用。第一个表正在进行表扫描,但在另一个表中找到足够的匹配行后,它将中止部分表扫描过程。>>当查询正在执行时,限制确实适用。谢谢。我不明白你的问题。您的实际用例是否受到影响?有时,您运行的测试SQL的运行路径与生产中的代码不同。也许你在某个地方做出了一个错误的假设,认为这个行动方针确实是正确的。你的数据索引是否正确?你的内容是否接受空值?+1是的,一个类比是阅读一本书。如果我让你阅读这本书的每一页,你就没有必要看目录或索引。你只是从头读到尾。是的,我已经很久没有在mysql中使用大表了。我现在又想起来了PSeems说MySQL优化器不使用索引不是因为它太聪明,而是因为列接受空值。要使用索引,需要明确告知CONTENT_ID不为NULL(即使联接中使用了列)。嗨,Eric,你能解释一下吗,为什么按查询顺序添加主键使用了索引?
SELECT*从表中选择,其中user\u id=18,名称为“%nxn%”order by updated desc LIMIT 10
-用户id和状态列(此查询中未使用状态)存在复合索引,但在按顺序条件添加了
id
(这是主键)之后(
按更新的描述、id asc下单
)现在使用复合索引进行查询?我不明白为什么不使用复合索引before@Andomar:不,错。虽然is会过滤掉空值,但MySQL优化器仍然需要被告知。MySQL会索引空值。这个答案完全错误。@Harrison:你能把代码发布到查询浏览器和c中吗见鬼(和我一样)?
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;
ALTER TABLE content_link MODIFY content_id NOT NULL