MySQL - 创建的索引不会显示为可能的密钥

时间:2017-10-09 22:31:56

标签: mysql indexing

我有下表(它有更多的数据列,删除它们因为它会很长):

CREATE TABLE `members` (
  `memberid` int(11) NOT NULL AUTO_INCREMENT,
  `firstname` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
  `lastname` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,  
  PRIMARY KEY (`memberid`),
  KEY `members_lname_ix` (`lastname`)
) ENGINE=InnoDB AUTO_INCREMENT=1019 DEFAULT CHARSET=utf8 
COLLATE=utf8_unicode_ci;

默认情况下,用户一次只能访问此表中的10-20行,并且通常按姓氏列排序,它是所有分页服务器端。所以我决定在lastname中添加一个索引以帮助排序,但索引似乎并没有像我期望的那样工作。当我跑EXPLAIN SELECT * FROM members ORDER BY lastname ASC时,我得到:

id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | extra
1  | simple      | members | ALL  | null          | null | null    | null | 711  | using filesort

我至少可以确认索引存在,因为如果我运行SHOW INDEX FROM members我得到:

Table   | Non_Unique | Key_name         | Seq_in_ix | Col_name | Collation | Cardinality | Sub part | Packed | Null    | Ix type
members | 0          | PRIMARY          | 1         | memberid | A         | 711         | null     | null   | (blank) | BTREE
members | 1          | members_lname_ix | 1         | lastname | A         | 711         | null     | null   | YES     | BTREE

如果我添加USE INDEX (members_lname_ix)两个possible_keys,则密钥将保持为空。但是,如果我添加FORCE INDEX (members_lname_ix),possible_keys保持为null,键显示成员_lname_ix。这是我第一次尝试应用索引,但对我来说这看起来并不直观 - 感觉mysql应该知道我为lastname创建了一个索引,不是吗?除非我误解了什么,否则我无法弄明白我在这里做错了什么。这里的解决方案是继续使用FORCE INDEX吗?

1 个答案:

答案 0 :(得分:0)

有两种方法可以执行该查询:

计划A(如您所料):

  1. 按顺序扫描索引,读取整个(估计的)711行。
  2. 随机查找数据BTree中的每一行。这涉及阅读整个数据集。
  3. 按顺序提供数据。
  4. B计划(它的作用):

    1. 扫描数据,读取所有711行。
    2. 对数据进行排序
    3. 提供已排序的数据。
    4. B计划根本没有触及索引;这被认为是比不必对数据进行排序更大的节省。

      在像你这样小的桌子里,很难看出速度的差异。 (在我的测试案例中,无论哪种方式都花了不到10毫秒。)在大表中,差异可能很大。

      要获得最佳分页效果,请参阅http://mysql.rjweb.org/doc.php/pagination