【发布时间】:2016-03-12 04:04:28
【问题描述】:
我有一些桌子:
object
person
project
[...] (some more tables)
type
对象表具有所有其他表的外键。
现在我进行如下查询:
SELECT * FROM object
LEFT JOIN person ON (object.person_id = person.id)
LEFT JOIN project ON (object.project_id = project.id)
LEFT JOIN [...] (all other joins)
LEFT JOIN type ON (object.type_id = type.id)
WHERE object.customer_id = XXX
ORDER BY object.type_id ASC
LIMIT 25
即使对于大型结果集,这也非常有效且快速。例如,我有 90000 个对象,查询大约需要 3 秒。结果非常大,因为表有很多列并且所有列都被获取。有关信息:我正在使用带有 Propel、InnoDB 和“doSelectJoinAll”功能的 Symfony。
但如果进行类似(按 type.name 排序)的查询:
SELECT * FROM object
LEFT JOIN person ON (object.person_id = person.id)
LEFT JOIN project ON (object.project_id = project.id)
LEFT JOIN [...] (all other joins)
LEFT JOIN type ON (object.type_id = type.id)
WHERE object.customer_id = XXX
ORDER BY type.name ASC
LIMIT 25
查询大约需要 200 秒!
解释:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
1 | SIMPLE | object | ref | object_FI_2 | object_FI_2 | 4 | const | 164966 | Using where; Using temporary; Using filesort
1 | SIMPLE | person | eq_ref | PRIMARY | PRIMARY | 4 | db.object.person_id | 1
1 | SIMPLE | ... | eq_ref | PRIMARY | PRIMARY | 4 | db.object...._id | 1
1 | SIMPLE | type | eq_ref | PRIMARY | PRIMARY | 4 | db.object.type_id | 1
我在进程列表中看到,MySQL 正在创建一个临时表,用于对连接表进行此类排序。
向 type.name 添加索引并没有提高性能。只有大约 800 行类型。
我发现很多连接和大结果是问题所在,因为如果我只使用一个连接进行查询,例如:
SELECT * FROM object
LEFT JOIN type ON (object.type_id = type.id)
WHERE object.customer_id = XXX
ORDER BY type.name ASC
LIMIT 25
它的工作速度与预期一样快。
有没有办法改进对包含许多连接表的大型结果集的此类排序查询?还是对连接表列进行排序只是一个坏习惯,无论如何都不应该这样做?
谢谢
【问题讨论】:
-
使用 EXPLAIN 结果编辑您的问题
-
好的,我为有问题的查询添加了解释结果
标签: mysql performance sorting join