2013-03-07 20 views
0

我试图优化MySQL表以获得更快的读取。读取与写入的比率约为100:1,因此我倾向于牺牲具有多个索引的写入性能。针对混合方向的多字段排序优化索引

我的表相关领域,我定义这个表默认的范围有以下几种,它包含了20多万条记录

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的documentati在ORDER BY子句中混合使用ASC和DESC时,不能使用复合索引进行排序
  • active是一个布尔标志,因此将其放在独立索引中没有任何意义(它只有2个可能的值),但它是它总是用在WHERE子句中,所以它应该出现在索引的某处以避免使用Where in Extra
  • position是一个很少可能的整数,它的使用范围始终是publication_date,所以我认为将它放在独立索引
  • 很多查询在where部分中使用publication_date,所以将它也放在独立索引中也是有用的,即使是多余的并且它是组合索引的第一列。

回答

0

一个问题是,您是按order by子句混合排序顺序。你可以反转你的位置(inverted_position = max_position - position),这样你也可以反转该列的排序顺序。

然后,您可以创建[publication_date,inverted_position]一个复合索引和条款更改为publication_date DESC,inverted_position DESC

active列应该很可能不是索引的一部分,因为它具有非常低的选择性。