【发布时间】:2012-03-17 02:55:49
【问题描述】:
我正在尝试一次从多个表中获取数据。在我的旧系统中,我会进行查询,获取所需的数据,然后将其用于下一个查询。我想避免进行多个查询,所以我将它们与连接结合起来:
SELECT `to`.`id` , `to`.`group`, `to`.`email`, `pTo`.`min_offer`, COUNT(`offerRes`.`id`), `settingsRes`.`email`
FROM `members` AS `to`
LEFT JOIN (
SELECT `id` , `min_offer`
FROM `profile`
) pTo ON pTo.id = to.id
LEFT JOIN (
SELECT `id`, `from`,`to`
FROM `offers`
) offerRes ON offerRes.from = ? && offerRes.to = to.id
LEFT JOIN (
SELECT `id`, `email`
FROM `user_settings`
) settingsRes ON settingsRes.id = to.id
WHERE to.id = ? LIMIT 1
我使用传入的 ID (to.id) 从配置文件表、报价表和用户设置表中获取结果。这些表都有一个PRIMARY id,所有内容都映射到该ID。我的 PHP 用户准备了语句,但是我替换了 ?在 PHPMyAdmin 中具有硬值。我的解释如下:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY to const PRIMARY PRIMARY 4 const 1
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 45
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 1
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 15
4 DERIVED user_settingsALL NULL NULL NULL NULL 15
3 DERIVED offers system NULL NULL NULL NULL 1
2 DERIVED profile ALL NULL NULL NULL NULL 45
由于我的查询基于主键 id,为什么 MySQL 可以执行简单的查找,但它会遍历配置文件字段中的所有 45 行?有什么办法让这个更有效吗?我想要的只是以下表格:
id (from members) - this is optional as this is what is obtained from the user and passed in to SELECT against
group (from members) - corresponding to the id that is passed in
email (from members) - corresponding to the id that is passed in
min_offer (from profile) - also corresponding to the id that is passed in
NUM_ROWS(from offers) - number of rows corresponding to the id taht is passed in and another number that is also passed in. The offers table has a PRIMARY id but it is a different ID than what is passed in.
email (from user_settings) - corresponding to the id that is passed in
【问题讨论】:
-
非INNER连接越多,查询效率越低。
-
据我所知,如果这些子查询中的任何一个不返回任何行,那么整个事情都会返回 NULL。这是不可取的。我仍然不明白为什么它在 idCol = someOtherIdCol 上执行 LEFT JOIN 时必须搜索所有 45 条记录。 ID 是主键。除非我读错了 EXPLAIN,否则它不应该搜索 45 行?
-
左连接应该检查 45 行。表成员的所有行都会在结果中,你找不到另一个表对应的行会有空字段
-
@Ignacio - 这种情况下的效率与连接的类型无关,它是使用派生表,可以直接访问表!
-
所以你告诉我执行多个查询会更快? SE:ECT
f1,f2FROMmemnbersWHEREid= ?限制 1 ... 选择f1FROMprofileWHEREid= ?限制 1. 至少这将利用主键并进行快速查找。任何将它们结合起来以提高代码美观和效率的方法(更少的 mysql 调用 = 我认为更好)
标签: php mysql optimization join