我有一张这样的表
CREATE TABLE IF NOT EXISTS `tbl_folder` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner_userid` int(11) NOT NULL,
`name` varchar(63) NOT NULL,
`description` text NOT NULL,
`visibility` tinyint(4) NOT NULL DEFAULT '2',
`num_items` int(11) NOT NULL DEFAULT '0',
`num_subscribers` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `owner_userid` (`owner_userid`),
KEY `vis_sub_item` (`visibility`,`num_subscribers`,`num_items`)
) ENGINE=InnoDB
因为我有一个可见性索引,num_subscribers和num_items,我希望只需要查看前15行,而EXPLAIN说55856行。任何的想法?感谢
EXPLAIN SELECT t.id, name, description, owner_userid, num_items, num_subscribers
FROM `tbl_folder` `t`
WHERE visibility =2
ORDER BY `t`.`num_subscribers` DESC , `t`.`num_items` DESC
LIMIT 15
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t ref vis_sub_item vis_sub_item 1 const 55856 Using where
答案 0 :(得分:2)
您的3字段索引看起来不错,EXPLAIN
很有希望。
虽然它显示“55856行”,但这只是EXPLAIN
提供的估算值。
从key_len =1
开始,您知道它使用复合索引的第一个字节作为相等/引用。
由于您的Extra
字段中没有提及任何文件排序,因此您知道索引正在处理ORDER BY
/ sorting 。
如果您查看handler_%
会话统计信息,则可以更好地了解实际读取的行数。
旁思:
由于你知道你最终要点击磁盘来检索你的行,如果99%的数据都有visibility=2
(只是推测),你可能会得到同样好/快的结果索引仅在num_subscribers
& num_items
。或者如果你在num_subscribers
上有一个索引,可以说是好/快,具体取决于它的基数/唯一性。
答案 1 :(得分:0)
我不认为EXPLAIN
会查看OFFSET
或LIMIT
子句。 EXPLAIN
应该表明查询将如何执行,它使用了什么键,如何连接表等。LIMIT
子句有点像一个帖子查询修饰符...现在我们知道了我们想要什么,只给他们第一个这么多。因此,rows字段包含查询中存在的可能行数。从那里,OFFSET
和LIMIT
会选择您想要的具体内容。
我认为如果你执行了SELECT
而没有EXPLAIN
,你就会得到你想要的记录数。
答案 2 :(得分:0)
是的,问题是您的索引不正确。我的意思是你索引所有3个字段,你的选择查询只检查一个。在MySQL索引中,2行分别与索引3行不同。
尝试
CREATE TABLE IF NOT EXISTS `tbl_folder` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner_userid` int(11) NOT NULL,
`name` varchar(63) NOT NULL,
`description` text NOT NULL,
`visibility` tinyint(4) NOT NULL DEFAULT '2',
`num_items` int(11) NOT NULL DEFAULT '0',
`num_subscribers` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `owner_userid` (`owner_userid`),
KEY `vis_index` (`visibility`),
KEY `vis_sub_item` (`num_subscribers`,`num_items`)
) ENGINE=InnoDB