无论如何,我都不是 DBA,但我认为我可以拥有简单的数据库。但是,这个查询让我难住了。
我有两张桌子。一个持有我网站上每个页面的名称。另一个为每次访问页面时保存一个记录。我想加入这两个表来找出我每个页面的平均执行时间和总所需时间,这样我就可以确定需要优化的地方。这是我的查询:
SELECT reqtemp.template_path, reqtemp.template_name,
round(AVG(req.request_execution_time)) AS week_avg_exec_time, COUNT(DISTINCT req.skey) AS week_count, SUM(req.request_execution_time) AS week_total_time,
round(AVG(req2.request_execution_time)) AS month_avg_exec_time, COUNT(DISTINCT req2.skey) AS month_count, SUM(req2.request_execution_time) AS month_total_time,
round(AVG(req3.request_execution_time)) AS old_avg_exec_time, COUNT(DISTINCT req3.skey) AS old_count, SUM(req3.request_execution_time) AS old_total_time
FROM log_exectime_request_tmp reqtemp
LEFT JOIN log_exectime_request req ON reqtemp.skey = req.log_exectime_req_tmp_skey
AND req.request_date >= DATE_SUB(Now(), INTERVAL 7 DAY)
LEFT JOIN log_exectime_request req2 ON reqtemp.skey = req2.log_exectime_req_tmp_skey
AND req2.request_date >= DATE_SUB(Now(), INTERVAL 30 DAY)
LEFT JOIN log_exectime_request req3 ON reqtemp.skey = req3.log_exectime_req_tmp_skey
AND req3.request_date >= DATE_SUB(Now(), INTERVAL 365 DAY)
AND req3.request_date <= DATE_SUB(Now(), INTERVAL 335 DAY)
GROUP by reqtemp.template_path, reqtemp.template_name
ORDER BY week_total_time DESC
据我了解,这应该在几毫秒内运行,较大的表中只有 2000 条记录。至少我希望,因为这最终需要在生产中运行数十万或数百万条记录。相反,我上次尝试它花了 53 分钟。“解释”显示它在 log_exectime_request_tmp 上进行表扫描,这很好,因为该表只有 83 条记录,并且它的两个列都在使用中。其他三个连接使用 skey 和 request_date 上的索引,这似乎也是正确的。
谁能提供一些优化建议?为什么这么小的桌子会导致这样的问题?我的查询构造不佳吗?
表格的 DDL 如下,虽然我找不到任何方法来附加文件来填写数据(我错过了吗?):
CREATE TABLE `log_exectime_request`
(
`skey` integer (11) NOT NULL AUTO_INCREMENT ,
`log_exectime_req_tmp_skey` integer (11),
`request_date` datetime,
`request_execution_time` integer (11),
`query_execution_time` integer (11),
`template_execution_time` integer (11),
`logging_execution_time` integer (11),
PRIMARY KEY (`skey`)
) TYPE=InnoDB CHARACTER SET latin1 COLLATE latin1_swedish_ci;
ALTER TABLE `elegantgalleries`.`log_exectime_request` ADD INDEX `date_tempSkey` (`log_exectime_req_tmp_skey`,`request_date` );
CREATE TABLE `log_exectime_request_tmp`
(
`skey` integer (11) NOT NULL AUTO_INCREMENT ,
`template_path` varchar (500),
`template_name` varchar (250),
PRIMARY KEY (`skey`)
) TYPE=InnoDB CHARACTER SET latin1 COLLATE latin1_swedish_ci;