1

我不擅长优化 SQL,但我需要这个查询尽可能快地运行。它将通过 PHP 脚本在大约 40 个不同的数据库上重复运行。然后 PHP 按时间顺序对结果进行排序。

SELECT DATE_FORMAT(lastmoddate, '%a %b %D, %Y  %l:%i%p') as lastmod,
       count(*) as num_modified,
       (select count(*) from store.item) as totalitems,
       UNIX_TIMESTAMP(lastmoddate) as timestamp
FROM store.item
group by lastmoddate
HAVING lastmoddate = MAX(lastmoddate)
order by lastmoddate desc
limit 1;

解释

  • lastmoddate是项目记录的最后修改日期
  • count(*) as num_modified是上次更新时修改的项目数
  • 查询获取表中的项目总数
  • UNIX_TIMESTAMP可能是不必要的,但我稍后在 PHP 中使用它进行排序。该结果与来自其他数据库的结果合并,然后进行排序。

所以最终目标是获取一个包含上次修改日期、在上次修改日期修改的项目数以及数据库中的总项目数的表。

子查询可能会被删除,但它似乎对速度影响不大。需要其他结果。如果 DATE_FORMAT 或 UNIX_TIMESTAMP 很慢,它们可以被删除,但它们会被 PHP 中的一些可能同样慢的东西所取代。(就像我说的,我对优化 SQL 没有任何兴趣。我感觉很好,只是获得了一个有效的查询。)

MySQL 5.5 和 PHP 5.3

4

2 回答 2

2

您正在尝试获取有关具有最大值的行的信息lastmoddate。您的查询正在聚合所有数据lastmoddate,然后选择最后一行。

相反,先进行过滤,然后进行聚合。您只会在输出中获得一行,因此您甚至不需要该group by子句。

该方法是计算子查询中的最大上次修改日期和总项目数。这是加入的,因此可以过滤数据:

select DATE_FORMAT(i.lastmoddate, '%a %b %D, %Y  %l:%i%p') as lastmod,
       COUNT(*) as NumModified,
       const.totalitems,
       UNIX_TIMESTAMP(i.lastmoddate) as timestamp
from store.item i cross join
     (select max(lastmoddate) as maxlastmoddate, count(*) as totalitems
     ) const
where i.lastmoddate = const.maxlastmoddate;

索引将进一步提高您的表现store.item(lastmoddate)

于 2013-05-16T18:33:24.177 回答
1

您可以做的一件事是选择 count(*) 一次并将其作为子查询删除。将它放在执行 40 次的循环之外。

你需要有条款吗?没有它你会得到同样的结果吗?我认为可以放在where子句中

WHERE lastmoddate = (select max(lastmoddate) from store.item i2)

确保您在 lastmoddate 上有一个索引。

于 2013-05-16T18:15:17.173 回答