【问题标题】:Query with JOIN slow使用 JOIN 查询慢
【发布时间】:2014-04-04 05:08:13
【问题描述】:

为什么我的查询需要大约 2 分钟来处理?

我需要从 8 个表中获取属性。

如何加入这些表并使其成为快速查询?

我想加入这些表的原因是因为我想从用户输入 progCode 中获取 fetchAll(PDO::FETCH_ASSOC)

这是我的查询:

"SELECT DISTINCT a.`ProgCode`, a.`Program` 
   FROM (select `i`.`name` AS `LC`,`f`.`name` AS `Intake`,`a`.`student_id` 
   AS `student_id`,`b`.`matricNo` 
   AS `matricNo`,`b`.`name` 
   AS `Nama`,`a`.`sem_id` 
   AS `sem_id`,`c`.`name` 
   AS `Sessi`,`e`.`code` 
   AS `ProgCode`,`e`.`name` 
   AS `Program`,`a`.`sub_id` 
   AS `sub_id`,`d`.`code` 
   AS `SubCode`,`d`.`name` 
   AS `Subject`,`a`.`grade` 
   AS `grade`,`h`.`credit` 
   AS `CurrentCreditHour`,`g`.`totalcredit` 
   AS `TotalCreditHour`,`g`.`gpa` 
   AS `GPA`,`g`.`cgpa` 
   AS `CGPA` from ((((((((`admin_sub_mark` `a` join `enrl_student` `b`) 
     join `struc_session` `c`) 
     join `struc_session` `f`) 
     join `struc_subject` `d`) 
     join `struc_program` `e`) 
     join `admin_sem_wise_cgpa` `g`) 
     join `admin_sem_wise_gpa` `h`) 
     join `struc_learningcentre` `i`) 
  where ((`b`.`id` = `a`.`student_id`) 
  and (`d`.`id` = `a`.`sub_id`) 
  and (`c`.`id` = `a`.`sem_id`) 
  and (`e`.`id` = `b`.`program_id`) 
  and (`f`.`id` = `b`.`intake_id`) 
  and (`i`.`id` = `b`.`learningCenter_id`) 
  and (`a`.`student_id` = `g`.`student_id`) 
  and (`a`.`sem_id` = `g`.`sem_id`) 
  and (`h`.`student_id` = `g`.`student_id`) 
  and (`h`.`sem_id` = `g`.`sem_id`)) order by `b`.`name`) a  
  ORDER BY `Program` ASC"

这是我的解释查询:

身份证|选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外的

1 |简单 |克 |全部 |空值 |空值 |空 |空| 6049 |使用临时的; 使用文件排序

1 |简单 | h |全部 |空 |空 |空 |空 | 6055 |使用位置 |

1 |简单 | c | eq_ref |初级 |初级 | 257 |教育aeu2.g.sem_id 1

1 |简单 |乙 | eq_ref |初级 |初级 | 257 |教育_aeu2.h.student_id 1 使用哪里

1 |简单 | f | eq_ref |初级 |初级 | 257 |教育_aeu2.b.intake_id 1

1 |简单 |电子| eq_ref |初级 |初级 | 257 |教育aeu2.b.program_id 1

1 |简单 |我 | eq_ref |初级 |初级 | 257 |教育_aeu2.b.learningCenter_id 1

1 |简单 |一个 |全部 |空 |空 |空 |空 | 17077 |在哪里使用

1 |简单 | d | eq_ref |初级 |初级 | 257 |教育aeu2.a.sub_id 1

【问题讨论】:

  • 首先对查询执行 EXPLAIN 并查看正在使用/未使用的索引
  • 为适当的字段使用索引...
  • MySQL 可以比我们更好地 EXPLAINEXPLAIN EXTENDED 你的查询,因为 MySQL 已经知道模式的样子
  • 如果您需要来自 8 个表和 1 个查询的数据,您应该再次查看您的数据库。您确定将数据划分为良好的表结构吗?
  • 是的..我可以使用该查询创建一个视图,但视图也很慢..所以我决定把它放在 php 代码中。

标签: php mysql


【解决方案1】:

您正在内部选择中检索大量字段并进行排序,然后忽略其中大部分字段并进行另一次排序。这会浪费时间

快速清理代码给出:-

SELECT DISTINCT 
   e.code AS ProgCode,
   e.name AS Program
FROM admin_sub_mark a 
JOIN enrl_student b ON b.id = a.student_id
JOIN struc_session c ON c.id = a.sem_id
JOIN struc_session f ON f.id = b.intake_id
JOIN struc_subject d ON d.id = a.sub_id
JOIN struc_program e ON e.id = b.program_id
JOIN admin_sem_wise_cgpa g ON a.student_id = g.student_id AND a.sem_id = g.sem_id
JOIN admin_sem_wise_gpa h ON h.student_id = g.student_id AND h.sem_id = g.sem_id
JOIN struc_learningcentre i ON i.id = b.learningCenter_id
ORDER BY e.name ASC

不确定是否需要访问所有表。

此外,您在表上有哪些索引?如果像这样的查询运行缓慢,那么罪魁祸首通常是索引,但在不知道它们是什么(或者更好的是,来自 EXPLAIN 的输出)的情况​​下,我们将难以提供任何有用的帮助

【讨论】:

  • 看解释似乎有几个问题。首先,在 admin_sem_wise_cgpa 和 admin_sem_wise_gpa 上,您需要将要使用的索引(可能是 student_id 和 sem_id 的覆盖索引)。此外,你们中的大多数键的长度似乎都是 257,这表明 id 字段存储在 VARCHAR(255) 字段中,这可能比使用 INT 主键慢很多。
  • 如何为他们创建索引?我需要输入那个查询吗?或调用该查询中的索引?
  • 非常感谢您的帮助。现在我的查询变得又快又猛!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-16
  • 2011-09-27
  • 1970-01-01
  • 2019-03-07
  • 2019-08-02
  • 2014-03-15
  • 1970-01-01
相关资源
最近更新 更多