5

我有一张这样的桌子

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
4

3 回答 3

2

您的 3 字段索引看起来不错并且EXPLAIN很有希望。

虽然它说“ 55856行”,但这只是EXPLAIN.

因为key_len =1,您知道它使用复合索引的第一个字节作为相等/引用。

由于您的字段中没有提到文件排序Extra,因此您知道ORDER BY/sorting正在由索引处理。

如果您检查handler_%会话统计信息,您将更好地了解实际读取了多少行。

侧面想法:

既然您知道您最终会使用磁盘来检索您的行,那么如果您的 99% 的数据都有(只是推测),那么您可能会在&visibility=2上使用复合索引获得同样好的/快速的结果。或者如果你有一个单一的索引,可以说是好/快,这取决于它的基数/唯一性。 num_subscribersnum_itemsnum_subscribers

于 2010-12-08T21:26:56.540 回答
0

我不认为这EXPLAIN着眼于OFFSETorLIMIT子句。 EXPLAIN应该指示查询将如何执行,它使用什么键,表如何连接等。该LIMIT子句有点像查询后修饰符......现在我们知道我们想要什么,只给他们第一个所以许多。因此,rows 字段包含查询中可能存在的行数。从那里,OFFSETLIMIT会选择你想要的特定的。

我想如果你执行你SELECTwithout EXPLAIN,你会得到你想要的记录数。

于 2010-12-08T20:27:08.493 回答
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
于 2010-12-08T20:48:57.353 回答