我试图找到一种方法来加快缓慢(filesort)MySQL查询。慢速查询多个地方,并按子句排序
表:
categories (id, lft, rgt)
questions (id, category_id, created_at, votes_up, votes_down)
例子查询:
SELECT * FROM questions q
INNER JOIN categories c ON (c.id = q.category_id)
WHERE c.lft > 1 AND c.rgt < 100
ORDER BY q.created_at DESC, q.votes_up DESC, q.votes_down ASC
LIMIT 4000, 20
如果我删除ORDER BY
条款,速度非常快。我知道MySQL不喜欢同一个子句中的DESC
和ASC
命令,所以我尝试将(created_at, votes_up)
复合索引添加到questions
表中,并从ORDER BY
子句中删除q.votes_down ASC
。这没有帮助,WHERE
子句似乎妨碍了这里的工作,因为它按来自另一个表(categories
)的列进行过滤。但是,即使它工作,它也不是很正确,因为我确实需要q.votes_down ASC
条件。
在这种情况下改善性能的策略是什么?如果可能,我宁愿避免重构表格。
编辑:
CREATE TABLE `categories` (
`id` int(11) NOT NULL auto_increment,
`lft` int(11) NOT NULL,
`rgt` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `lft_idx` (`lft`),
KEY `rgt_idx` (`rgt`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `questions` (
`id` int(11) NOT NULL auto_increment,
`category_id` int(11) NOT NULL,
`votes_up` int(11) NOT NULL default '0',
`votes_down` int(11) NOT NULL default '0',
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `questions_FI_1` (`category_id`),
KEY `votes_up_idx` (`votes_up`),
KEY `votes_down_idx` (`votes_down`),
KEY `created_at_idx` (`created_at`),
CONSTRAINT `questions_FK_1` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE q ALL questions_FI_1 NULL NULL NULL 31774 Using filesort
1 SIMPLE c eq_ref PRIMARY,lft_idx,rgt_idx PRIMARY 4 ttt.q.category_id 1 Using where
您是否对所有列进行了索引? – BenOfTheNorth 2012-02-26 12:04:37
您没有为2个表格发布'SHOW CREATE TABLE'的输出,也没有发布'EXPLAIN'的输出。你也有'LIMIT 4000,20'。如果您需要帮助分析查询,请发布上述查询的输出。 – 2012-02-26 12:06:48
@Ben Griffiths:所有列都有索引。 – Ree 2012-02-26 12:07:31