7

我有一个基于 3 列的复合索引,其中两列在我的查询中受到限制,第三列是按子句排序,但 mysql 不使用索引进行排序。

解释 select * from videos where public_private='public' and approved='yes' order by number_of_views desc;

+----+-------------+--------+------+-------------- ------------------+------+---------+------+------- --+------------------+
| 编号 | 选择类型 | 表| 类型 | 可能的键 | 关键 | key_len | 参考 | 行 | 额外 |
+----+-------------+--------+------+-------------- ------------------+------+---------+------+------- --+------------------+
| 1 | 简单 | 视频 | 全部 | 已批准,已批准_3,已批准_2 | 空 | 空 | 空 | 1476818 | 使用哪里;使用文件排序 |
+----+-------------+--------+------+-------------- ------------------+------+---------+------+------- --+------------------+

表结构如下:

CREATE TABLE `videos` (
  `indexer` int(9) NOT NULL auto_increment,
  `user_id` int(9) default NULL,
  `public_private` varchar(24) default NULL,
  `approved` varchar(24) default NULL,
  `number_of_views` int(9) default NULL,
  PRIMARY KEY  (`indexer`),
  KEY `approved` (`approved`,`user_id`),
  KEY `approved_3` (`approved`,`public_private`,`indexer`),
  KEY `approved_2` (`approved`,`public_private`,`number_of_views`),
) ENGINE=MyISAM AUTO_INCREMENT=1969091 DEFAULT CHARSET=utf8 |

我应该怎么做才能强制mysql使用索引对结果进行排序?

4

5 回答 5

14

我相信您的查询可能与表中的大部分数据匹配。在这种情况下,MySQL 优化器通常选择进行表扫描并完全忽略索引,因为它实际上比通过额外读取整个索引并使用它来挑选数据的麻烦更快。所以在这种情况下,我猜这public_private='yes' and approved='yes'与你桌子的很大一部分相匹配。因此,如果 MySQL 因此跳过使用索引,那么它也不能用于排序。

如果您真的希望它使用索引,那么解决方案是使用FORCE INDEX

select * from videos FORCE INDEX (approved_2) where public_private='public' and approved='yes' order by number_of_views desc;

但是,我会运行一些测试以确保您得到的结果实际上比 MySQL 优化器选择的要快。显然,优化器在选择排序时确实存在一些问题,所以你绝对可以试一试,看看你是否得到了改进的性能。

于 2009-07-17T18:06:30.890 回答
1

顺序在复合键中确实很重要。如果您只想number_of_views使用approved_2键进行排序,请更改:

KEY `approved_2` (`approved`,`public_private`,`number_of_views`)

至:

KEY `approved_2` (`number_of_views`,`approved`,`public_private`)

MySQL 中的复合键从左到右工作。在上面的示例中,使用 、 和隐式声明的键number_of_viewsapproved以下public_private位置创建索引:

  • number_of_views
  • number_of_views,approved
  • number_of_views, approved,public_private
于 2009-07-17T18:19:17.573 回答
0

这应该有效:

`select * from videos where approved='yes' and public_private='public' order by number_of_views desc;` 

如果没有,只需在number_of_views.

这必须有效。

(mysql基本上遵循左右顺序。因此,如果不按此顺序使用,您的索引将approved不起作用。即,您可以使用从左边开始的所有三个,从左边开始的2或最左边的1。但它不起作用如果你不使用最左边的那个,那就是这个主意。)public_privatenumber_of_views

使用单独的索引会number_of_views自动排序,这可能会有所帮助order by——不过我敢肯定。

于 2011-03-08T18:00:44.630 回答
-2

顺序在复合键中很重要。我忘记了规则,但以不同的顺序尝试。

于 2009-07-17T10:38:55.617 回答
-2

在列上添加一个单独的索引,number_of_views然后看看它是否有效。

如果键是 3 列的组合,则只有在使用全部 3 列执行操作时才会使用该特定键

于 2009-07-17T11:36:09.870 回答