php - 为什么这个 JOIN 效率低下?

标签 php mysql optimization join

我想一次从多个表中获取数据。在我的旧系统中,我会进行查询,获取所需的数据,然后将其用于下一个查询。我想避免进行多次查询,所以我将它们与连接结合起来:

 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,所有内容都映射到该 primary 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

最佳答案

Why is MySQL going through all 45 rows in the profile field when it can do a simple lookup as my query is based on the PRIMARY key id?

因为您要加入子查询的结果,其中将包括表中的每条记录:

LEFT JOIN (
  SELECT `id` , `min_offer`
  FROM `profile`
) pTo ON pTo.id = to.id

-- etc.

相反,直接加入表:

LEFT JOIN `profile` AS pTo ON pTo.id = to.id

LEFT JOIN `offers` AS offerRes ON offerRes.from = ? && offerRes.to = to.id

LEFT JOIN `user_settings` AS settingsRes ON settingsRes.id = to.id

关于php - 为什么这个 JOIN 效率低下?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9746860/

相关文章:

php - 代码点火器 : what is the best practice for caching?

php - 如何正确防止未登录的用户访问php页面

MySQL InnoDB : Index Locks - Advice Needed

php - 将 .htaccess 转换为 PHP 脚本的 Nginx 配置时出现问题

mysql - 在 Express.js 应用程序中处理 Mysql 数据库的最佳方法是什么?

mysql - 如何创建 SQL 查询以获取另一列的每个 GROUP'ed BY 值的列的唯一值

mysql - python3 mysqldb 游标.fetchone

algorithm - 查询n次时如何改进Dijkstra算法?

mysql - SQL 查询卡在统计状态

php - 如何在mysql中插入日期和时间并查看