【发布时间】:2015-08-19 00:35:39
【问题描述】:
我试图在查询中解释mysql的explain(以两种不同的方式编写),这是表格:
create table text_mess(
datamess timestamp(3) DEFAULT 0,
sender bigint ,
recipient bigint ,
roger boolean,
msg char(255),
foreign key(recipient)
references users (tel)
on delete cascade
on update cascade,
primary key(datamess,sender)
)
engine = InnoDB
这是第一种查询:
EXPLAIN
select /*!STRAIGHT_JOIN*/datamess, sender,recipient,roger,msg
from text_mess join (select max(datamess)as dmess
from text_mess
where roger = true
group by sender,recipient) as max
on text_mess.datamess=max.dmess ;
这是第二个:
EXPLAIN
select /*!STRAIGHT_JOIN*/datamess, sender,recipient,roger,msg
from (select max(datamess)as dmess
from text_mess
where roger = true
group by sender,recipient) as max
join
text_mess
on max.dmess = text_mess.datamess ;
这两个查询问的是同一个问题,唯一的区别是ref_table(driving_table)的顺序,第一种情况是text_mess,第二种情况是子查询。
第一个结果:
id select_type table type possible_keys key key_len ref rows Extra
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 PRIMARY text_mess ALL PRIMARY null null null 294225 null
1 PRIMARY derived2 ref auto_key0 auto_key0 7 inextremis.text_mess.datamess 10 Using index
2 DERIVED text_mess ALL recipient null null null 294225 Using where; Using temporary; Using filesort
第二个结果:
id select_type table type possible_keys key key_len ref rows Extra
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 PRIMARY <derived2> ALL null null null null 294225 Using where
1 PRIMARY text_mess ref PRIMARY PRIMARY 6 max.dmess 1 null
2 DERIVED text_mess ALL recipient null null null 294225 Using where; Using temporary; Using filesort
如您所见,区别在于前两行的顺序,我的问题尤其是第二行(查询速度更快)
第二行应该是内表,但如果是这样,为什么列 ref 告诉我:max.dmess,那应该是 ref 表(子查询)的列。
最后一行是否提到了第一行是如何构建的? 最后,您认为有更高效的查询吗?
【问题讨论】:
-
在
INNER JOINs 上,建议将行数较少的表格放在左侧(即第一个表格)。如果您首先放置最大的表,MySQL 查询计划器能够为您交换表(无论您先放置哪个表,它都会在EXPLAIN上产生相同的结果)。在这种情况下,它无法执行此魔法,因为在您的查询中,JOINed 表之一不是表,而是子查询,这会阻止它知道哪个表更小。 -
我的问题是explain的结果:特别是id为1的行,如下:将explain结果的第一行解释为表的“处理”是正确的连接的左侧和第二行作为连接右侧的表的“处理”,最后最后一行是表的“处理”。并正确解释(在第二个查询解释中)第二行上 ref 列的 max.dmess,作为将每行与表 text_mess 的行进行比较的列(通过键找到:PRIMARY)
-
为了获得更好的性能,请创建索引
roger asc, sender asc, recipient asc, datamess desc(或全部desc)。 -
您能否对表进行分析并重新运行查询。他们还有同样的解释吗?