我认为这些链接可以帮助优化这个查询: http:
//dev.mysql.com/doc/refman/5.5/en/order-by-optimization.html
http://dev.mysql.com/doc/refman/ 5.5/en/internal-temporary-tables.html
第一个结论- 无法避免文件排序(临时表),因为ORDER BY
子句中的查询包含来自两个表的列,并且还包含一个表达式,因此 mySql 无法使用索引对其进行优化:
在某些情况下,MySQL 无法使用索引来解析 ORDER BY ......
这些情况包括:
- 您将 ORDER BY 与包含键以外的术语的表达式一起使用列名
- 您正在连接许多表,并且 ORDER BY 中的列并非全部来自用于检索行的第一个非常量表。
第二个结论- 因为表包含一个 TEXT 列,MySql 不能使用修改(优化)的文件排序算法,但必须使用原始算法。原始算法的一个缺点是它读取表行两次,并且以随机方式读取它们,这比顺序读取要慢得多:
这种方法的一个问题是它读取了两次行:一次是在评估 WHERE 子句时,另一次是在对对值进行排序之后。即使第一次连续访问了行(例如,如果进行了表扫描),第二次访问它们也是随机的。(排序键是有序的,但行位置不是。)
第三个结论——由于表包含一个 TEXT 列,MySql 不能使用内存中的临时表,而必须将其存储在磁盘上:
某些情况会阻止使用内存中的临时表,在这种情况下,服务器会使用磁盘表来代替:
- 表中存在 BLOB 或 TEXT 列
考虑到上述情况,将 TEXT 列移动到另一个表中:
create table downloads_description(
lid int(11) not null unique,
description text,
constraint dd_fk foreign key (lid)
references downloads_downloads( lid )
);
insert into downloads_description( lid, description )
select lid, description
from downloads_downloads;
alter table downloads_downloads
drop column description;
然后将查询重写为:
SELECT
d.url,
d.lid,
d.title,
dd.description,
d.date,
d.hits,
d.downloadratingsummary,
d.totalvotes,
d.totalcomments,
d.filesize,
d.version,
d.homepage,
d.ns_compat,
d.ns_des_img,
t.type
FROM downloads_downloads d
JOIN(
select d.lid, t.type
FROM downloads_downloads d
LEFT JOIN downloads_type t
ON d.lid = t.lid
WHERE cid = 81
ORDER BY FIELD(COALESCE(t.type,-1),1,-1,2,4,5,0,3),
d.date DESC
limit 0,20
) t ON d.lid = t.lid
JOIN downloads_description dd
ON dd.lid = d.lid
ORDER BY FIELD(COALESCE(t.type,-1),1,-1,2,4,5,0,3),
d.date DESC
;