(为什么)MySQL在这种情况下不能使用索引?

时间:2012-06-18 09:15:14

标签: mysql database indexing

1 - PRIMARY用于辅助索引,例如(PRIMARYcolumn1

上的二级索引

2 - 我知道只要一部分用于范围扫描,mysql就无法继续使用索引的其余部分,但是:IN (...,...,...)不被视为范围,是吗?是的,这是一个范围,但我在mysqlperformanceblog.com上读到,根据索引的使用,IN的行为与BETWEEN不同。

有人能确认这两点吗?或者告诉我为什么这不可能?或者它是如何可能的?

更新:

链接:
http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/
http://www.mysqlperformanceblog.com/2006/08/14/mysql-followup-on-union-for-query-optimization-query-profiling/comment-page-1/#comment-952521

更新2:嵌套SELECT的示例:

SELECT * FROM user_d1 uo 
WHERE EXISTS (
    SELECT 1 FROM `user_d1` ui
    WHERE ui.birthdate BETWEEN '1990-05-04' AND '1991-05-04'
    AND ui.id=uo.id
)    
ORDER BY uo.timestamp_lastonline DESC
LIMIT 20

因此,外部SELECT使用timestamp_lastonline进行排序,内部PK与外部连接或birthdate进行过滤。

如果MySQL无法在范围扫描中使用索引并进行排序,那么还有哪些其他选项而不是此查询?

3 个答案:

答案 0 :(得分:2)

主键的列当然可以用在二级索引中,但它通常不值得。主键保证唯一性,因此其后列出的任何列都不能用于范围查找。它唯一有用的时候是查询可以单独使用索引

对于嵌套选择,额外的复杂性不应该超越最简单的查询:

SELECT * FROM user_d1 uo 
WHERE uo.birthdate BETWEEN '1990-05-04' AND '1991-05-04'
ORDER BY uo.timestamp_lastonline DESC
LIMIT 20

MySQL将在birthdate索引或timestamp_lastonline索引之间进行选择,根据该索引,它感觉最有可能扫描较少的行。在任何一种情况下,列都应该是索引中的第一列。 birthdate索引也会带来排序惩罚,但如果大量最近用户的出生日期超出该范围,则可能是值得的。

如果您希望控制订单或可能提高效果,(timestamp_lastonline, birthdate)(birthdate, timestamp_lastonline)索引可能有所帮助。如果它没有,并且你真的需要先根据生日来选择,那么你应该从内部查询中选择而不是对其进行过滤:

SELECT * FROM (
    SELECT * FROM user_d1 ui
    WHERE ui.birthdate BETWEEN '1990-05-04' AND '1991-05-04'
) as uo
ORDER BY uo.timestamp_lastonline DESC
LIMIT 20

即使这样,MySQL的优化器可能会选择重写您的查询,如果它找到timestamp_lastonline索引但没有birthdate索引。

是的,IN (..., ..., ...)的行为与BETWEEN不同。只有后者才能有效地在索引上使用范围扫描;前者会单独查找每个项目。

答案 1 :(得分:0)

2. IN明显不同于BETWEEN。如果您在该列上有索引,BETWEEN将需要获得起点,并且全部完成。如果您有IN,它将在索引值中按值查找匹配值,因此它将查找值,与有时与BETWEEN的{​​{1}}相比较的值。< / p>

答案 2 :(得分:0)

  1. 是@Andrius_Naruševičius是正确的 IN 语句只是 EQUALS或EQUALS或EQUALS的简写没有固有的顺序,因为BETWEEN是一个比较运算符隐含的大于或小于,因此绝对喜欢索引

  2. 老实说,我不知道你在谈论什么,但似乎你问的是一个很好的问题我只是没有概念它是什么:-)。你是说主键不能包含第二个索引吗?因为它绝对可以。主键永远不需要被索引,因为它总是被自动索引,所以如果你得到一个错误/警告(我假设你是?)关于补充索引那么它不是第二个,第三个索引导致它它是PRIMARY KEY不需要它,你提到这可能是错误。说过我不知道你问了什么问题 - 这是我对你实际问题的最佳猜测的答案。