37

这是我一直以来的疑问。

据我所知,索引的顺序很重要。所以索引 like[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 列上会发生什么?

4

3 回答 3

63

当您的查询条件仅适用于索引的一部分时,索引顺序很重要。考虑:

  1. SELECT * FROM table WHERE first_name="john" AND last_name="doe"

  2. SELECT * FROM table WHERE first_name="john"

  3. SELECT * FROM table WHERE last_name="doe"

如果您的索引是 ( first_name, last_name) 查询 1 和 2 将使用它,查询 #3 不会。如果您的索引是 ( last_name, first_name) 查询 1 和 3 将使用它,查询 #2 不会。在任何一种情况下,更改 WHERE 子句中的条件顺序均无效。

详情在这里

更新
如果上述情况不清楚 - 如果查询条件中的列形成索引的最左侧前缀,MySQL 只能使用索引。上面的查询 #2 不能使用 ( last_name, first_name) 索引,因为它仅基于first_name并且不是 ( , ) 索引first_name的最左侧前缀。last_namefirst_name

查询中的条件顺序无关紧要;上面的查询 #1 将能够很好 地使用 ( last_name, ) 索引,因为它的条件是and ,并且,它们一起形成 ( , ) 索引的最左边的前缀。first_namefirst_namelast_namelast_namefirst_name

于 2009-08-09T21:05:44.073 回答
5

ChssPly76 是正确的,布尔表达式的顺序不必与索引中列的顺序相匹配。布尔运算符是可交换的,并且 MySQL 优化器足够聪明,在大多数情况下知道如何将表达式与索引匹配。

我还想补充一点,您应该学习如何使用EXPLAINMySQL 的功能,以便您自己查看优化器将为给定查询选择哪些索引。

于 2009-08-09T22:21:21.500 回答
3

为什么不稍微扩展答案以使所有内容都变得一目了然。

如果表有一个多列索引,优化器可以使用索引的任何最左边的前缀来查找行。例如,如果您在 上具有三列索引,则您在、和(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 开发

于 2014-04-06T12:15:52.773 回答