Mysql左外连接花了太长时间来回应php

时间:2014-10-26 01:57:37

标签: mysql

我的数据库中有近10000条记录。当查询没有加入时,通过PHP发送到mysql的查询工作得非常快。但是当我们使用左外连接连接表时,它非常慢。

这是我的疑问。

    $sql = "select 
rollno,
stuname,
total,
ifnull(sum(fpaid),0) as feepaid,
total-COALESCE(sum(fpaid),0) as balance,
status,
comments,
category
from 
    (select
        studet.rollno as rollno,
        studet.stuname as stuname,
        studet.course as course,
        studet.branch as branch,
        studet.category as category,
        studet.year as year,
        studet.total as total,
        studet.status as status,
        studet.comments as comments,
        studet.academic as academic ,
        stufeeref.feepaid as fpaid
        from studet
        left outer join stufeeref
        on studet.rollno = stufeeref.rollno
        and studet.year = stufeeref.year
    ) as T
where  branch='$branch'
and year='$year'
and academic='$academic'
and course='$course'
group by rollno,year"; 

请告诉我如何优化我的查询。  提前谢谢。

2 个答案:

答案 0 :(得分:0)

首先,为什么使用子查询?

select s.rollno, s.stuname, s.total, ifnull(sum(sr.fpaid), 0) as feepaid,
       s.total-COALESCE(sum(sr.fpaid),0) as balance,
       s.status, s.comments, s.category
from studet s left outer join
     stufeeref sr
     on s.rollno = sr.rollno and s.year = sr.year
where s.branch='$branch' and s.year='$year' and s.academic='$academic' and s.course='$course'
group by s.rollno, s.year;

现在您的查询可以利用索引。您想要的两个索引是studet(branch, year, academic, course)stufeeref(rollno, year, fpaid)

答案 1 :(得分:0)

删除内联视图查询。这不是必需的。它只会导致MySQL做更多的工作。

外部查询中的谓词不会被推入内联视图。您实际上是在创建表的副本(派生表),并针对该表运行查询。并且该派生表没有任何索引,它正在对派生表中的每一行进行全面扫描。

SELECT s.rollno
     , s.stuname
     , s.total
     , IFNULL(SUM(r.fpaid),0) AS feepaid
     , s.total-COALESCE(SUM(r.fpaid),0) AS balance
     , s.status
     , s.comments
     , s.category
  FROM studet s
  LEFT
  JOIN stufeeref r
    ON r.rollno = s.rollno
   AND r.year   = s.year
 WHERE s.branch   = '$branch'
   AND s.year     = '$year'
   AND s.academic = '$academic'
   AND s.course   = '$course'
 GROUP BY s.rollno, s.year

为获得最佳性能,您需要提供合适的索引。对于stufeeref表,覆盖索引:

ON stufeeref (rollno, year, fpaid)

由于连接谓词,您首先需要rollno和year列;包括fpaid列意味着MySQL可以完全从索引中满足查询,而无需从基础表中检索块。

对于studet表,具有等式谓词的列应该是第一个。

ON studet (branch, year, academic, course)

(该索引中这四列的顺序并不重要;关键是MySQL可以通过非常快速地消除大量行进行检查来有效地定位行。)


此外,如果未正确转义值(例如,使用mysqli_real_escape_string函数),则在SQL文本中包含变量是SQL注入漏洞。

例如:

 WHERE s.branch   = '". $mysqli->real_escape_string( $branch   ) ."'
   AND s.year     = '". $mysqli->real_escape_string( $year     ) ."'
   AND s.academic = '". $mysqli->real_escape_string( $academic ) ."'
   AND s.course   = '". $mysqli->real_escape_string( $course   ) ."'