我有下表(它有更多的数据列,删除它们因为它会很长):
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
吗?
答案 0 :(得分:0)
有两种方法可以执行该查询:
计划A(如您所料):
B计划(它的作用):
B计划根本没有触及索引;这被认为是比不必对数据进行排序更大的节省。
在像你这样小的桌子里,很难看出速度的差异。 (在我的测试案例中,无论哪种方式都花了不到10毫秒。)在大表中,差异可能很大。
要获得最佳分页效果,请参阅http://mysql.rjweb.org/doc.php/pagination