2013-08-20 21 views
0

我很努力地理解,如果我已经正确索引这个查询,它有点慢,我觉得它可以使用优化。 MySQL的70年5月1日找到这个MySQL查询的最佳索引

select snaps.id, snaps.userid, snaps.ins_time, usr.gender 
    from usersnaps as snaps 
    join user as usr on usr.id = snaps.userid 
    left join user_convert as conv on snaps.userid = conv.userid 
    where (conv.level is null or conv.level = 4) and snaps.active = 'N' 
and (usr.status = "unfilled" or usr.status = "unapproved") and usr.active = 1 
     order by snaps.ins_time asc 

usersnaps表(无关DETA拆除,面积约25万条记录):

CREATE TABLE IF NOT EXISTS `usersnaps` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `userid` int(11) unsigned NOT NULL DEFAULT '0', 
    `picture` varchar(250) NOT NULL, 
    `active` enum('N','Y') NOT NULL DEFAULT 'N', 
    `ins_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`,`userid`), 
    KEY `userid` (`userid`,`active`), 
    KEY `ins_time` (`ins_time`), 
    KEY `active` (`active`) 
) ENGINE=InnoDB; 

用户表(无关DETA拆除,面积约30万条记录):

CREATE TABLE IF NOT EXISTS `user` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `active` tinyint(1) NOT NULL DEFAULT '1', 
    `status` enum('15','active','approval','suspended','unapproved','unfilled','rejected','suspended_auto','incomplete') NOT NULL DEFAULT 'approval', 
    PRIMARY KEY (`id`), 
    KEY `status` (`status`,`active`) 
) ENGINE=InnoDB; 

user_convert table(size about:60k records):

CREATE TABLE IF NOT EXISTS `user_convert` (
    `userid` int(10) unsigned NOT NULL, 
    `level` tinyint(4) NOT NULL, 
    UNIQUE KEY `userid` (`userid`), 
    KEY `level` (`level`) 
) ENGINE=InnoDB; 

解释延期退货:

id select_type table type possible_keys    key  key_len ref    rows filtered Extra 
1 SIMPLE  snaps ref  userid,default_pic,active active 1  const   65248 100.00  Using where; Using filesort 
1 SIMPLE  usr  eq_ref PRIMARY,active,status  PRIMARY 4  snaps.userid 1  100.00  Using where 
1 SIMPLE  conv eq_ref userid      userid 4s  snaps.userid 1  100.00  Using where 
+0

从来没有错误 –

+0

版本的MySQL? –

+0

已更新至(5.1.70)版 –

回答

0

Using filesort可能是你的表现杀手。

您需要来自usersnaps的记录,其中active ='N',并且您需要它们按ins_time排序。

ALTER TABLE usersnaps ADD KEY active_ins_time (active,ins_time); 

索引存储在排序的顺序,并阅读排序顺序...因此,如果优化器选择该索引,它会去活跃=“N”和记录 - 嘿,看那个 - 他们已经排序ins_time - 因为该指数。所以当它读取索引引用的行时,结果集内部已经按照您想要的顺序排列,并且优化器应该认识到这一点...不需要filesort。

+0

完美谢谢。我添加了索引,没有更多的文件,并且性能得到了改善 –

0

我建议改变用户ID指数有active第一和userid更高版本(你不使用它现在假设)。

这应该使这个查询更有用。

+0

它用于其他查询,但我可以将userid添加到'active'索引,以便它(active,userid)? –

+0

我建议给予一个尝试,它应该对这个查询有很大的帮助,因为MySQL目前正在使用'active'索引,该索引可能具有非常低的基数(2),这使得它在大多数查询中都毫无用处。 – Wolph

+0

我试了一下,解释扩展输出的唯一区别是捕捉行上的“行”从65248增加到74987.性能方面,它几乎相同 –