1

鉴于以下 -

drop table if exists learning_indexes;

create table learning_indexes (
    id INT NOT NULL,
    col1 CHAR(30),
    col2 CHAR(30),
    col3 CHAR(30), 
    PRIMARY KEY (id),
    index idx_col1 (col1),
    index idx_col1_col2 (col1,col2)
);

explain

select
    col1,col2
from
    learning_indexes
where
    col1 = 'FOO'
    and col2 = 'BAR'

为什么 MySQL 选择 idx_col1 而不是 idx_col1_col2?

+----+-------------+------------------+------+------------------------+----------+---------+-------+------+-------------+
| id | select_type | table            | type | possible_keys          | key      | key_len | ref   | rows | Extra       |
+----+-------------+------------------+------+------------------------+----------+---------+-------+------+-------------+
|  1 | SIMPLE      | learning_indexes | ref  | idx_col1,idx_col1_col2 | idx_col1 | 91      | const |    1 | Using where |
+----+-------------+------------------+------+------------------------+----------+---------+-------+------+-------------+

这是我的版本信息 -

+-------------------------+---------------------+
| Variable_name           | Value               |
+-------------------------+---------------------+
| innodb_version          | 1.1.8               |
| protocol_version        | 10                  |
| slave_type_conversions  |                     |
| version                 | 5.5.29              |
| version_comment         | Source distribution |
| version_compile_machine | i386                |
| version_compile_os      | osx10.7             |
+-------------------------+---------------------+
4

2 回答 2

0

我无法在这里解释你的情况,但有时 MySQL 只是选择了“错误”的索引。也许数据库足够小,以至于它知道在这种情况下它没有任何区别。

这个查询非常简单,它应该知道哪个索引是最合适的。

我可以根据经验说,当查询变得越来越复杂,特别是当表变得非常大时,MySQL 有时(随机?)决定选择另一个索引并使用它,然后查询可以从 0.01 秒到 100+ 秒,因此,如果您知道哪个索引是正确的,请使用 FORCE INDEX()。即使你使用 USE INDEX() MySQL 有时会选择另一个索引,对查询速度有各种破坏性的结果。

于 2013-04-09T18:04:41.323 回答
0

我同意 Floaf 的观点,即 MySQL 有时会选择错误的索引,但我认为这里不是这种情况。MySQL 将行数和数据结构包括在其决定选择哪个索引中。

对于像这样一个相当简单的查询,如果表包含少于大约 100 行甚至是空的,MySQL 可能根本不会使用任何索引。仅扫描所有表行似乎比使用索引在计算上更便宜。在您的解释计划中,您可以看到“key”列显示 idx_col1,但“Extra”列没有显示“使用索引”。

如果表包含超过 100 行,MySQL 将开始使用 idx_col1。解释计划将向您展示这一点。只有当 col1 中实际包含字符串 'FOO' 的行超过大约 100 行时,MySQL 才会注意到使用 idx_col1 并不能充分减少暂定结果集,因为它必须扫描剩余的 100 行以查找值 '在 col2 中的 BAR'。因此,它将切换到 idx_col1_col2。

我不完全确定 MySQL 如何快速决定使用哪个索引,但我认为这与启发式和索引中各个行的基数有关,即索引行的“选择性”程度。

于 2013-04-09T18:29:51.683 回答