我正在开发一个时间表应用程序,并编写一个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中运行了这个查询,它没有任何问题。
需要帮助了解可能导致执行缓慢的原因。
答案 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添加到查询中,这就是您获得快速结果的原因。
答案 2 :(得分:1)
首先:修改您的查询,使其看起来像Spencer给出的那个
当您的应用程序崩溃时,您会收到错误消息吗?还是只是停下来?
你可以尝试:
ini_set('max_execution_time', 0);
在你的PHP代码中。这将最大执行时间设置为无限制。因此,如果没有错误,您的脚本应该执行到最后。因此,您可以查看您的查询是否获得了所需的结果。
同样,测试结束了
的查询 LIMIT 10
这样可以大大加快您的查询速度,因为它只会占用前十个结果。 您可以稍后将此值更改为更适合您需求的值。除非您绝对需要完整的结果集,否则我建议您始终在查询中使用LIMIT。