重写mysqlselect以减less时间并将tmp写入磁盘

我有一个MySQL查询需要几分钟,这是不是很好,因为它是用来创build一个网页。

使用三张表:poster_data包含个别海报的信息。 poster_categories列出了所有类别(电影,艺术等),而poster_prodcat列出了posterid编号和它可以在的类别,例如一个海报可以有多行,比如电影,印第安纳琼斯,哈里森福特,冒险片等。

这是慢速查询:

select * from poster_prodcat, poster_data, poster_categories where poster_data.apnumber = poster_prodcat.apnumber and poster_categories.apcatnum = poster_prodcat.apcatnum and poster_prodcat.apcatnum='623' ORDER BY aptitle ASC LIMIT 0, 32 

据解释:

说明

这是花了几分钟。 Poster_data只有80多万行,而poster_prodcat只有1700多万行。 其他类别查询与此select几乎不明显,而poster_prodcat.apcatnum ='623'有约400,000结果,并写出到磁盘

希望你觉得这有帮助 – http://pastie.org/1105206

 drop table if exists poster; create table poster ( poster_id int unsigned not null auto_increment primary key, name varchar(255) not null unique ) engine = innodb; drop table if exists category; create table category ( cat_id mediumint unsigned not null auto_increment primary key, name varchar(255) not null unique ) engine = innodb; drop table if exists poster_category; create table poster_category ( cat_id mediumint unsigned not null, poster_id int unsigned not null, primary key (cat_id, poster_id) -- note the clustered composite index !! ) engine = innodb; -- FYI http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html select count(*) from category count(*) ======== 500,000 select count(*) from poster count(*) ======== 1,000,000 select count(*) from poster_category count(*) ======== 125,675,688 select count(*) from poster_category where cat_id = 623 count(*) ======== 342,820 explain select p.*, c.* from poster_category pc inner join category c on pc.cat_id = c.cat_id inner join poster p on pc.poster_id = p.poster_id where pc.cat_id = 623 order by p.name limit 32; id select_type table type possible_keys key key_len ref rows == =========== ===== ==== ============= === ======= === ==== 1 SIMPLE c const PRIMARY PRIMARY 3 const 1 1 SIMPLE p index PRIMARY name 257 null 32 1 SIMPLE pc eq_ref PRIMARY PRIMARY 7 const,foo_db.p.poster_id 1 select p.*, c.* from poster_category pc inner join category c on pc.cat_id = c.cat_id inner join poster p on pc.poster_id = p.poster_id where pc.cat_id = 623 order by p.name limit 32; Statement:21/08/2010 0:00:00.021: Query OK 

您列出的查询是如何最终查询将看起来像? (所以他们有apcatnum = / ID /?)

其中poster_data.apnumber = poster_prodcat.apnumber和poster_categories.apcatnum = poster_prodcat.apcatnum和poster_prodcat.apcatnum ='623'

poster_prodcat.apcatnum ='623'将极大地减lessmysql必须处理的数据集,因此这应该是查询的第一个分析部分。

然后继续交换比较,以便最大限度地减less数据集最先被parsing。

您可能还想尝试子查询。 我不知道这会有所帮助,但MySQL可能不会先获得所有3个表,但首先做子查询,然后再做另一个。 这应该尽量减less查询时的内存消耗。 虽然这不是一个选项,如果你真的想select所有的列(因为你使用*)。

你需要在POSTER_DATA的apnumber上有一个索引。 扫描841,152条logging正在杀死性能。

看起来像查询是使用apptitle索引来获得sorting,但它正在做一个完整的扫描过滤结果。 我认为这可能会有所帮助,如果你在poster_data的apptitle和apnumber上都有一个复合索引。 MySQL然后可以使用它来执行sorting顺序和filter。

 create index data_title_anum_idx on poster_data(aptitle,apnumber);