【问题标题】:Mysql left outer join is taking too long time to respond from phpMysql左外连接需要很长时间才能从php响应
【发布时间】:2014-10-26 12:26:22
【问题描述】:

我的数据库中有近 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"; 

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

【问题讨论】:

  • 您可以为studetstufeeref 表添加表定义吗?使用SHOW CREATE TABLE studet 获取表定义。
  • 你能把show create table studet;show create table stufeeref的结果贴出来吗?查看表格将有助于确定是否有任何索引可能有帮助。此外,可能会删除子查询

标签: mysql


【解决方案1】:

删除内联视图查询。这不是必需的。它只会导致 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 可以通过非常快速地消除被检查的大量行来有效地定位行。)


另外,在 SQL 文本中包含变量是一个 SQL 注入漏洞,如果值没有正确转义,例如使用 mysqli_real_escape_string 函数。

例如:

 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   ) ."'

【讨论】:

  • 非常感谢您的先生。与发布的查询相比,您提供的查询工作得更快。再次非常感谢您。您的查询非常好,再次恭喜您的大脑非常好。
【解决方案2】:

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

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)

【讨论】:

  • 谢谢先生。查询正在快速处理。非常感谢您的大力支持和阁下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多