【问题标题】:Optimize index for multi field ordering with mixed direction优化混合方向多字段排序的索引
【发布时间】:2013-03-07 18:56:15
【问题描述】:

我正在尝试优化 MySQL 表以加快读取速度。读写比约为 100:1,所以我倾向于牺牲多索引的写入性能。

我的表的相关字段如下,它包含大约 200000 条记录

CREATE TABLE `publications` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  -- omitted fields
  `publicaton_date` date NOT NULL,
  `active` tinyint(1) NOT NULL DEFAULT '0',
  `position` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  -- these are just attempts, they are not production index
  KEY `publication_date` (`publication_date`),
  KEY `publication_date_2` (`publication_date`,`position`,`active`)
) ENGINE=MyISAM;`enter code here`

由于我使用 Ruby on Rails 来访问此表中的数据,因此我为该表定义了一个默认范围

default_scope where(:active => true).order('publication_date DESC, position ASC')

即默认情况下,该表中的每个查询都会使用以下 SQL 片段自动完成,因此您可以假设几乎所有查询都会有这些条件

WHERE `publications`.`active` = 1 ORDER BY publication_date DESC, position

所以我主要对优化这种查询感兴趣,加上在 WHERE 条件中带有 publication_date 的查询。

我尝试了以下索引的各种组合(也可以同时使用多个)

`publication_date`
`publication_date`,`position`
`publication_date`,`position`,`active`

但是,像这个这样的简单查询仍然没有正确使用索引并使用文件排序

SELECT  `publications`.* FROM `publications`  
WHERE `publications`.`active` = 1 
AND (id NOT IN (35217,35216,35215,35218)) 
ORDER BY publication_date DESC, position
LIMIT 8 OFFSET 0
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: publications
         type: ALL
possible_keys: PRIMARY
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 34903
        Extra: Using where; Using filesort
1 row in set (0.00 sec)

关于我的问题的一些注意事项:

  • 根据 MySQL 文档,当您在 ORDER BY 子句中混合 ASC 和 DESC 时,复合索引不能用于排序
  • active 是一个布尔标志,所以把它放在一个独立的索引中没有意义(它只有 2 个可能的值),但它总是在 WHERE 子句中使用,所以它应该出现在索引中的某个地方以避免在 Extra 中使用 where
  • position 是一个整数,几乎没有可能的值,它总是在publication_date 范围内使用,所以我认为将它放在独立索引中是没有用的
  • 许多查询在 where 部分使用 publication_date,因此将它也放在独立索引中会很有用,即使是多余的并且它是复合索引的第一列。

【问题讨论】:

    标签: mysql optimization indexing


    【解决方案1】:

    一个问题是您在 order by 子句中混合了排序顺序。您可以反转您的位置 (inverted_position = max_position - position) 以便您也可以反转该列的排序顺序。

    然后您可以在 [publication_date,inverted_position] 上创建一个复合索引,并将您的 order by 子句更改为 publication_date DESC,inverted_position DESC

    active 列很可能不属于索引,因为它的选择性非常低。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-05
      • 2013-10-18
      • 1970-01-01
      • 2012-05-01
      • 2016-10-24
      • 1970-01-01
      • 1970-01-01
      • 2014-01-09
      相关资源
      最近更新 更多