【问题标题】:Optimizing my mysql query to use index for sorting优化我的 mysql 查询以使用索引进行排序
【发布时间】:2010-11-11 15:57:51
【问题描述】:

我有一个基于 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使用索引对结果进行排序?

【问题讨论】:

    标签: optimization mysql indexing query-optimization


    【解决方案1】:

    我相信您的查询可能与表中的大部分数据匹配。在这种情况下,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 优化器选择的要快。显然优化器does have some issues 可以选择订购,所以你绝对可以试一试,看看你是否能提高性能。

    【讨论】:

    • FORCE INDEX 解决了这个问题。查询现在执行得更快了,而且您对匹配大部分数据库的查询是正确的。
    【解决方案2】:

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

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

    到:

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

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

    • number_of_views
    • number_of_views, approved
    • number_of_views, approved, public_private

    【讨论】:

    • 此解决方案将剥夺MySQL 过滤前两个字段并在第三个字段上排序的可能性。
    • 他问为什么不使用索引进行排序。
    • 您建议的索引只能用于排序。 @op提出的索引可用于过滤和进行排序。您的索引不能用于过滤,但可以(或不可以)用于排序。
    • 我同意这是一个更好的解决方案,我只是想回答所提出的非常具体的问题。
    【解决方案3】:

    这应该可行:

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

    如果没有,只需在 number_of_views 上创建一个单独的索引。

    这必须有效。

    (mysql 基本上遵循左右顺序。所以你在approved、public_private、number_of_views 上的索引如果不在这个顺序中使用将不起作用。即,你可以使用从左到右的所有三个,从左起的 2或者最左边的1。但是如果你不使用最左边的那它就行不通了,就是这样。)

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

    【讨论】:

    • 仅添加索引number_of_views 并不能解决问题,因为将考虑满足where 条件的索引。在 OP 的回答中,应该使用索引 approved_2,而不是分别在 approved, public_private 和 number_of_views 上使用索引。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • 没有。正确的是:如果一个键是 3 列的组合,它将在使用第一列或前两列的组合或所有三列时使用该特定键
      猜你喜欢
      • 2016-08-25
      • 2021-08-09
      • 1970-01-01
      • 1970-01-01
      • 2012-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多