Mysql查询需要花费大量时间来执行

时间:2015-06-27 02:06:59

标签: php mysql

我正在开发一个时间表应用程序,并编写一个PHP代码来获取所有时间表直到日期。这是我写的用于获取时间表的查询 -

SELECT a.accnt_name, u.username, DATE_FORMAT(t.in_time, '%H:%i') inTime, DATE_FORMAT(t.out_time, '%H:%i') outTime, DATE_FORMAT(t.work_time, '%H:%i') workTime, w.wrktyp_name, t.remarks, DATE_FORMAT(t.tmsht_date, '%d-%b-%Y') tmshtDate, wl.loctn_name, s.serv_name, t.status_code, t.conv_kms convkms, t.conv_amount convamount FROM timesheets t, accounts a, services s, worktypes w, work_location wl, users WHERE a.accnt_code=t.accnt_code and w.wrktyp_code=t.wrktyp_code and wl.loctn_code=t.loctn_code and s.serv_code=t.serv_code and t.usr_code = u. ORDER BY tmsht_date desc

where子句包含从各个表中获取相应代码的实际值的子句。

问题是这个查询花了很多时间执行,应用程序在几分钟结束时崩溃。

我在phpmyadmin中运行了这个查询,它没有任何问题。

需要帮助了解可能导致执行缓慢的原因。

3 个答案:

答案 0 :(得分:2)

使用EXPLAIN查看查询的执行计划。确保MySQL具有合适的索引,并且正在使用这些索引。

查询文本似乎缺少此处的列名...

  t.usr_code = u.    ORDER
                 ^^^

我们可以“猜测”那应该是u.usr_code,但这只是猜测。

应该返回多少行?结果集有多大?

您的客户端是否试图将所有行“存储”在内存中,并因为内存不足而崩溃?

如果是这样,我建议您不要这样做,并根据需要获取行。

或者,考虑在WHERE子句中添加一些额外的谓词,只返回所需的行,而不是表中的所有行。

这是2015年。是时候抛弃用于连接操作的旧式逗号语法,而是使用JOIN关键字,并将连接谓词从WHERE子句移动到ON子句。并格式化它。数据库并不关心,但它会使那些需要解密SQL语句的穷人更容易理解。

  SELECT a.accnt_name
       , u.username
       , DATE_FORMAT(t.in_time  ,'%H:%i') AS inTime
       , DATE_FORMAT(t.out_time ,'%H:%i') AS outTime
       , DATE_FORMAT(t.work_time,'%H:%i') AS workTime
       , w.wrktyp_name
       , t.remarks
       , DATE_FORMAT(t.tmsht_date, '%d-%b-%Y') AS tmshtDate
       , wl.loctn_name
       , s.serv_name
       , t.status_code
       , t.conv_kms      AS convkms
       , t.conv_amount   AS convamount 
    FROM timesheets t
    JOIN accounts a
      ON a.accnt_code = t.accnt_code
    JOIN services s
      ON s.serv_code = t.serv_code 
    JOIN worktypes w
      ON w.wrktyp_code = t.wrktyp_code
    JOIN work_location wl
      ON wl.loctn_code = t.loctn_code 
    JOIN users
      ON u.usr_code = t.usr_code
   ORDER BY t.tmsht_date DESC

对格式化的日期列进行排序非常奇怪。您希望以“日期”顺序返回结果的次数更多,而不是按年份中的月份和日期的字符串顺序。 (你真的想在今年之前对当天的价值进行排序吗?)

<强>后续

如果使用来自不同客户端(相同数据库,同一用户)的整个结果集(大约720行)快速完成同样的完全查询,则问题可能是其他而不是此SQL言。

我们不希望执行SQL语句导致PHP“崩溃”。

如果要存储整个结果集(例如,使用mysqli store_result),则需要有足够的内存。但是选择列表中的十三个表达式看起来都相对较短(格式化日期,名称和代码),我们不希望“备注”超过几KB。

为了进行调试,正如其他人所建议的那样,尝试在查询中添加LIMIT子句,例如: LIMIT 1并观察行为。

或者,使用虚拟查询进行测试;使用保证返回特定值和特定行数的查询。

  SELECT 'morpheus'             AS accnt_name
       , 'trinity'              AS username
       , '01:23'                AS inTime
       , '04:56'                AS outTime
       , '00:45'                AS workTime
       , 'neo'                  AS wrktyp_name
       , 'yada yada yada'       AS remarks
       , '27-May-2015'          AS tmshtDate
       , 'zion'                 AS loctn_name
       , 'nebuchadnezzar'       AS serv_name
       , ''                     AS status_code
       , '123'                  AS convkms
       , '5678'                 AS convamount 

我怀疑查询是您正在观察的行为的根本原因。我怀疑问题出在代码中的其他地方。

How to debug small programs http://ericlippert.com/2014/03/05/how-to-debug-small-programs/

答案 1 :(得分:1)

phpadmin会自动将LIMIT添加到查询中,这就是您获得快速结果的原因。

  1. 检查表格中的行数
  2. 使用限制
  3. 运行查询

答案 2 :(得分:1)

首先:修改您的查询,使其看起来像Spencer给出的那个

当您的应用程序崩溃时,您会收到错误消息吗?还是只是停下来?

你可以尝试:

ini_set('max_execution_time', 0);
在你的PHP代码中

。这将最大执行时间设置为无限制。因此,如果没有错误,您的脚本应该执行到最后。因此,您可以查看您的查询是否获得了所需的结果。

同样,测试结束了

的查询
 LIMIT 10

这样可以大大加快您的查询速度,因为它只会占用前十个结果。 您可以稍后将此值更改为更适合您需求的值。除非您绝对需要完整的结果集,否则我建议您始终在查询中使用LIMIT。