Mysql 混合方向多字段排序的索引优化

Mysql 混合方向多字段排序的索引优化,mysql,optimization,indexing,Mysql,Optimization,Indexing,我正在尝试优化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, `activ

我正在尝试优化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`
因为我使用RubyonRails访问这个表中的数据,所以我为这个表定义了一个默认范围,即

default_scope where(:active => true).order('publication_date DESC, position ASC')
i、 默认情况下,此表中的每个查询都将使用以下SQL片段自动完成,因此您可以假设几乎所有查询都具有这些条件

WHERE `publications`.`active` = 1 ORDER BY publication_date DESC, position
所以我主要感兴趣的是优化这类查询,以及在WHERE条件下使用publication_date的查询

我尝试了以下不同组合的索引(同时也尝试了多个索引)

然而,像这样一个简单的查询仍然不能正确地使用索引,并且使用filesort

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文档,当您在ORDERBY子句中混合使用ASC和DESC时,复合索引不能用于排序
  • active
    是一个布尔标志,因此将其放在独立索引中没有意义(它只有两个可能的值),但它总是在WHERE子句中使用,因此它应该出现在索引中的某个位置,以避免额外使用WHERE in
  • position
    是一个可能值很少的整数,它的作用域总是限定在
    publication\u date
    上,因此我认为在独立索引中使用它是没有用的
  • 许多查询在where部分使用
    publication\u date
    ,因此将其也包含在独立索引中是很有用的,即使它是多余的,并且是复合索引的第一列

一个问题是,您在ORDERBY子句中混合了排序顺序。您可以反转您的位置(反转的位置=最大位置-位置),这样您也可以反转该列上的排序顺序

然后,您可以在[publication\u date,inversed\u position]上创建一个复合索引,并将order by子句更改为publication\u date DESC,inversed\u position DESC

活性列很可能不是索引的一部分,因为它的选择性非常低

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)