40

在以下查询中

SELECT  col1,col2
FROM    table1
WHERE   col3='value1'
  AND   col4='value2'

如果我有 2 个单独的索引,一个在col3上,另一个在col4上,其中哪一个将用于此查询?

我在某处读到,对于查询中的每个表,只使用一个索引。这是否意味着查询无法同时使用两个索引?

其次,如果我同时使用col3col4创建了一个复合索引,但在WHERE子句中只使用col3会不会降低性能?例子:

SELECT  col1,col2
FROM    table1
WHERE   col3='value1'

最后,在所有情况下都使用覆盖索引更好吗?MISAM 和 innodb 存储引擎有区别吗?

4

4 回答 4

46

覆盖指数与综合指数不同。

如果我有 2 个单独的索引,一个在 col3 上,另一个在 col4 上,其中哪一个将用于此查询?

具有最高基数的索引。
MySQL 会统计哪些索引具有哪些属性。
将使用具有最大区分能力的索引(如 MySQL 的统计数据所示)。

我在某处读到,对于查询中的每个表,只使用一个索引。这是否意味着查询无法同时使用两个索引?

您可以使用子选择。
或者甚至更好地使用包含 col3 和 col4 的复合索引。

其次,如果我同时使用 col3 和 col4 创建了一个复合索引,但在 WHERE 子句中只使用 col3 会不会降低性能?例子:

复合索引
正确的术语是compound索引,而不是复合索引。
仅使用复合索引的最左侧部分。
所以如果索引定义为

index myindex (col3, col4)  <<-- will work with your example.
index myindex (col4, col3)  <<-- will not work. 

见:http ://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html

请注意,如果您选择最左侧的字段,则可以避免在 where 子句中不使用索引的该部分。
假设我们有一个复合索引

Myindex(col1,col2)

SELECT col1 FROM table1 WHERE col2 = 200  <<-- will use index, but not efficiently
SELECT * FROM table1 where col2 = 200     <<-- will NOT use index.  

这样做的原因是第一个查询使用覆盖索引并对其进行扫描。
第二个查询需要访问表,因此扫描索引没有意义。
这仅适用于 InnoDB。

什么是覆盖索引
覆盖索引是指查询中选择的所有字段covered都由索引选择的情况,在这种情况下,InnoDB(不是 MyISAM)永远不会读取表中的数据,而只会使用索引中的数据,显着加快选择。
请注意,在 InnoDB 中,主键包含在所有二级索引中,因此在某种程度上,所有二级索引都是复合索引。
这意味着如果您在 InnoDB 上运行以下查询:

SELECT indexed_field FROM table1 WHERE pk = something

MySQL 将始终使用覆盖索引并且不会访问实际表。 尽管它可以使用覆盖索引,但它会更喜欢 ,PRIMARY KEY因为它只需要命中一行。

于 2011-11-21T14:28:46.057 回答
5

我赞成Johan 的完整回答,但我认为他关于二级索引的以下陈述是不正确和/或令人困惑的;

Note that in InnoDB the primary key is included in all secondary indexes, 
so in a way all secondary indexes are compound indexes.

This means that if you run the following query on InnoDB:

SELECT indexed_field FROM table1 WHERE pk = something

MySQL will always use a covering index and will not access the actual table.

虽然我同意二级索引中包含主键,但我不同意 MySQL在此处指定的 SELECT 查询中“将始终使用覆盖索引”。

要了解原因,请注意在这种情况下始终需要进行全索引“扫描”。这与“查找”操作不同,而是对二级索引内容进行 100% 扫描。这是因为二级索引不是按主键排序的;它按“indexed_field”排序(否则它不会用作索引!)。

In light of this latter fact, there will be cases where it is more efficient to "seek" the primary key, and then extract indexed_field "from the actual table," not from the secondary index.

于 2013-11-21T19:46:04.020 回答
1

这是我经常听到的一个问题,并且由于以下原因引起了很多混乱:

  • 多年来 mySQL 的差异。多年来,索引和多索引支持发生了变化(即将被支持)

  • InnoDB / myISAM 差异有一些关键差异(如下),但我不相信多个索引是其中之一

MyISAM 较旧但经过验证。MyISAM 表中的数据分为三个不同的文件:表格式、数据和索引。
InnoDB 比 MyISAM 相对更新,并且是事务安全的。InnoDB 还提供行锁定,而不是表锁定,这增加了多用户并发性和性能。InnoDB 也有外键约束。
由于其行锁定功能,InnoDB 非常适合高负载环境。

为了确定事情,请确保使用 explain_plan 来分析查询执行。

于 2011-11-21T14:36:13.460 回答
-1

复合指数与复合指数不同。

  • 复合索引涵盖过滤器、连接和选择条件中的所有列。所有这些列都相应地存储在整个索引 B 树中的所有索引页上。
  • 复合索引涵盖了 B 树中的所有过滤器和连接键列,但仅将选择列保留在叶页上,因为它们不会被搜索,而只会被提取!这样可以节省空间,从而创建更少的索引页,从而加快 I/O。
于 2013-06-03T12:34:15.903 回答