【问题标题】:MySQL Indexes on InnoDB table - not working right?InnoDB 表上的 MySQL 索引 - 不能正常工作?
【发布时间】:2011-11-16 21:40:21
【问题描述】:

我正在阅读《高性能 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,使用索引。但不是每当我做 SELECT FullName .... WHERE FullName = 'Jeff'..

我对索引一点也不熟悉,我试图绕着它们绕圈子,对此有点困惑。如果我引用索引列,他们不应该返回 Using Index 吗?

谢谢。

【问题讨论】:

    标签: mysql indexing innodb


    【解决方案1】:

    使用索引并不意味着它看起来意味着什么。看看覆盖索引。如果它说“使用索引”,则意味着 mysql 可以在不读取实际行的情况下为您的查询返回数据。 SELECT * - 仅当表的偶数列在索引中时才能使用覆盖索引。通常情况并非如此。

    我似乎记得 High Performance Mysql 中的一个章节,其中谈到了覆盖索引以及如何读取 EXPLAIN 结果。

    【讨论】:

    • 谢谢,所以基本上我的索引应该没问题,额外的只是告诉我它是否可以使用索引返回结果,或者它是否需要实际搜索表?
    • 对。您要求的所有数据都在索引本身中
    【解决方案2】:

    您使用的是什么版本的 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)
    

    正如预期的那样,它能够从全名索引中获取全名列,所以这是一个仅索引查询。

    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)
    

    搜索全名但获取主键也是一个仅索引查询,因为 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)
    

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

    【讨论】:

    • 我正在使用 5.5.11 ,我想我只是没有正确理解索引的概念,但是您的回答让我有了更好的理解
    猜你喜欢
    • 2022-01-06
    • 2013-01-26
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多