1 - PRIMARY
用于辅助索引,例如(PRIMARY
,column1
)
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无法在范围扫描中使用索引并进行排序,那么还有哪些其他选项而不是此查询?
答案 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)
是@Andrius_Naruševičius是正确的 IN 语句只是 EQUALS或EQUALS或EQUALS的简写没有固有的顺序,因为BETWEEN是一个比较运算符隐含的大于或小于,因此绝对喜欢索引
老实说,我不知道你在谈论什么,但似乎你问的是一个很好的问题我只是没有概念它是什么:-)。你是说主键不能包含第二个索引吗?因为它绝对可以。主键永远不需要被索引,因为它总是被自动索引,所以如果你得到一个错误/警告(我假设你是?)关于补充索引那么它不是第二个,第三个索引导致它它是PRIMARY KEY不需要它,你提到这可能是错误。说过我不知道你问了什么问题 - 这是我对你实际问题的最佳猜测的答案。