mysql 多列索引不起作用(如预期的那样)?

Posted

技术标签:

【中文标题】mysql 多列索引不起作用(如预期的那样)?【英文标题】:mysql multi column index not working (as expected)? 【发布时间】:2011-05-22 10:44:13 【问题描述】:

我有一张这样的桌子

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

【问题讨论】:

将您的 SQL 包装在“代码块”标签中,以便我们更容易阅读。它有助于它脱颖而出并使其更易于阅读。 【参考方案1】:

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

虽然它说“55856 行”,但这只是EXPLAIN 提供的估计

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

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

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

旁白:

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

【讨论】:

【参考方案2】:

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

我想如果你在没有EXPLAIN 的情况下执行你的SELECT,你会得到你想要的记录数。

【讨论】:

【参考方案3】:

是的,问题是您的索引不正确。我的意思是您索引了所有 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

【讨论】:

以上是关于mysql 多列索引不起作用(如预期的那样)?的主要内容,如果未能解决你的问题,请参考以下文章

在 knexjs mysql 中取联合多列后总和不起作用

数据存储查询不起作用,要求的索引比预期的多

Grails 多列索引

位置服务关闭和打开时地理定位不起作用

UITableView 部分顺序不起作用

水平居中元素文本对齐中心不起作用