InnoDB表上的MySQL索引 - 不正常工作?

时间:2011-11-16 21:40:21

标签: mysql indexing innodb

我正在阅读高性能MySQL这本书,并且正在使用新的数据库来测试一些事情。

我不确定我做错了什么..

我有一张名为table_users

的表格

结构:

ID(Integer)
FullName(Char)
UserName(Char)
Password(Char)
SecurityID(TinyINT)
LocationID(TinyINT)
Active(TinyINT)

我的索引如下:

PRIMARY : ID
FullName : UNIQUE : FullName
FK_table_users_LocationID (foreign key reference) : INDEX : LocationID
FK_table_users_SecurityID (foreign key reference) : INDEX : SecurityID
Active : INDEX : Active

所有人都是BTREE

在阅读本书时,我试图使用以下mysql语句来查看SELECT语句所涉及的额外内容

EXPLAIN
SELECT * FROM table_users WHERE
FullName = 'Jeff';

无论WHERE语句指向此调用的是什么,额外的结果都是无效或使用where。如果我选择ID ... WHERE FullName ='Jeff'它返回使用where,Using Index。但不是每当我执行SELECT FullName .... WHERE FullName ='Jeff'..

我对索引并不熟悉,并且试图绕过他们,对此有点混淆。如果我引用索引列,它们不应该返回使用索引吗?

感谢。

2 个答案:

答案 0 :(得分:2)

使用索引并不意味着它的意思。看看覆盖索引。如果它说“使用索引”,则意味着mysql可以在不读取实际行的情况下返回查询数据。 SELECT * - 只有在表中的列甚至在索引中时才能使用覆盖索引。通常情况并非如此。

我似乎记得高性能Mysql中的章节讨论了覆盖索引以及如何阅读EXPLAIN结果。

答案 1 :(得分:1)

您使用的是哪个版本的MySQL?这是我在Percona Server 5.5.16上运行的测试:

mysql> create table table_users ( 
  id int auto_increment primary key, 
  fullname char(20), 
  username char(20), 
  unique key (fullname)
);
Query OK, 0 rows affected (0.03 sec)

mysql> insert into table_users values (default, 'billk', 'billk');
Query OK, 1 row affected (0.00 sec)

mysql> explain select * from table_users where fullname='billk'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: table_users
         type: const
possible_keys: fullname
          key: fullname
      key_len: 21
          ref: const
         rows: 1
        Extra: 
1 row in set (0.00 sec)

这表明它正在使用全名索引,以常量值查找,但它不是仅索引查询。

mysql> explain select fullname from table_users where fullname='billk'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: table_users
         type: const
possible_keys: fullname
          key: fullname
      key_len: 21
          ref: const
         rows: 1
        Extra: Using index
1 row in set (0.00 sec)

这是预期的,它可以从fullname索引中获取fullname列,因此这是一个仅索引查询。

mysql> explain select id from table_users where fullname='billk'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: table_users
         type: const
possible_keys: fullname
          key: fullname
      key_len: 21
          ref: const
         rows: 1
        Extra: Using index
1 row in set (0.00 sec)

在fullname上搜索但是获取主键也是一个仅索引查询,因为InnoDB二级索引的叶节点(例如唯一键)隐式包含主键值。因此,此查询能够遍历BTREE以获取全名,并且作为奖励,它也会获得ID。

mysql> explain select fullname, username from table_users where fullname='billk'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: table_users
         type: const
possible_keys: fullname
          key: fullname
      key_len: 21
          ref: const
         rows: 1
        Extra: 
1 row in set (0.00 sec)

只要select-list包含任何不属于索引的列,它就不再是仅索引查询。首先,它在BTREE中搜索全名,以查找主键值。然后它使用该id值来遍历聚簇索引的BTREE,这就是InnoDB存储整个表的方式。在那里,它找到给定行的其他列,包括用户名。