这是我永远的问题。
据我所知,指数的顺序很重要。因此像[first_name, last_name]
这样的索引与[last_name, first_name]
不一样,对吧?
如果我只定义第一个索引,是否意味着它只用于
SELECT * FROM table WHERE first_name="john" AND last_name="doe";
而不是
SELECT * FROM table WHERE last_name="doe" AND first_name="john";
由于我使用的是ORM,因此我不知道这些列的调用顺序。这是否意味着我必须在所有排列上添加索引?如果我有一个2列索引,这是可行的,但如果我的索引在3或4列上会发生什么?
答案 0 :(得分:47)
当您的查询条件仅适用于索引的 PART 时,索引顺序很重要。考虑:
SELECT * FROM table WHERE first_name="john" AND last_name="doe"
SELECT * FROM table WHERE first_name="john"
SELECT * FROM table WHERE last_name="doe"
如果您的索引是(first_name
,last_name
),则查询1和2将使用它,查询#3则不会。
如果您的索引是(last_name
,first_name
),则查询1和3将使用它,查询#2则不会。在任何一种情况下,更改WHERE子句中的条件顺序都无效。
详情为here
<强>更新强>:
如果上述情况不明确 - 如果查询条件中的列形成索引的最左前缀,MySQL只能使用索引。上面的查询#2无法使用(last_name
,first_name
)索引,因为它仅基于first_name
而first_name
不是(last_name
的最左前缀,first_name
)索引。
查询中的条件顺序无关紧要;上面的查询#1将能够使用(last_name
,first_name
)索引就好了,因为它的条件是first_name
和last_name
,并且它们组合在一起形成最左边的(last_name
,first_name
)索引的前缀。
答案 1 :(得分:5)
ChssPly76是正确的,布尔表达式的顺序不必与索引中的列顺序匹配。布尔运算符是commutative,并且MySQL优化器足够聪明,知道在大多数情况下如何将表达式与索引匹配。
我还想补充一点,你应该学习如何使用MySQL的EXPLAIN
功能,这样你就可以自己查看优化器为给定查询选择哪些索引。
答案 2 :(得分:2)
为什么不稍微延长答案,让所有事情一下子变得清晰。
如果表具有多列索引,则优化程序可以使用索引的任何最左前缀来查找行。例如,如果您在(col1, col2, col3)
上有一个三列索引,则您已在(col1)
,(col1, col2)
和(col1, col2, col3)
上编制了索引搜索功能。
如果列不构成索引的最左前缀,则MySQL无法使用索引。假设您有SELECT语句:
SELECT * FROM tbl_name WHERE col1=val1;
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
SELECT * FROM tbl_name WHERE col2=val2;
SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
如果(col1, col2, col3)
上存在索引,则只有前两个查询使用索引。第三个和第四个查询确实涉及索引列,但(col2)
和(col2, col3)
不是(col1, col2, col3)
的最左前缀。 - MySQL dev