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