我正在尝试优化 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 中使用 whereposition
是一个可能值很少的整数,并且它总是使用范围,publication_date
所以我认为将它放在独立索引中是没有用的- 许多查询
publication_date
在 where 部分中使用,因此将它也放在独立索引中会很有用,即使是多余的并且它是复合索引的第一列。