繁体   English   中英

“大约一小时前”PHP / SQL中的逻辑以及它如何影响性能?

[英]“About a hour ago” logic in PHP / SQL and how it affects performance?

最近我一直在面对“X小时前”,“X天前”功能的网站。 (包括stackoverflow)

就像,Anil在一个小时前玩了一场比赛。 两天前Anil平了。 Anil刚才发表了这条评论。

我知道可以通过一个小函数轻松完成,该函数计算到当前时间的旧时间,以秒(或毫秒)获得差异并相应地返回字符串值。

我想问的是;

  1. 如何以最专业的方式完成? 使用PHP计算时间差或在查询时根据我们的SQL计算它?
  2. 它不会降低性能吗? 想象一个包含100条注释的页面,该函数将工作100次,因此页面加载速度会变慢。

PS。 我不是在寻找脚本。

通常的方法是使用普通的SQL查询来收集整数时间的差异,然后使用PHP / Javascript进行转换。 换句话说,没有什么花哨的。 这是大多数Twitter包装器中使用的PHP脚本:

/**
* Formats a timestamp nicely with an adaptive "x units of time ago" message.
* Based on the original Twitter JavaScript badge. Only handles past dates.
* @return string Nicely-formatted message for the timestamp.
* @param $time Output of strtotime() on your choice of timestamp.
*/
function niceTime($time) {
  $delta = time() - $time;
  if ($delta < 60) {
    return 'less than a minute ago.';
  } else if ($delta < 120) {
    return 'about a minute ago.';
  } else if ($delta < (45 * 60)) {
    return floor($delta / 60) . ' minutes ago.';
  } else if ($delta < (90 * 60)) {
    return 'about an hour ago.';
  } else if ($delta < (24 * 60 * 60)) {
    return 'about ' . floor($delta / 3600) . ' hours ago.';
  } else if ($delta < (48 * 60 * 60)) {
    return '1 day ago.';
  } else {
    return floor($delta / 86400) . ' days ago.';
  }
}
?>

这通常是如此之快,以至于它应该比平常花费更少的时间。 如果您在页面上的计算量少于300左右,则不应该看到性能下降。

我认为性能含义是可以忽略的。 您也可以在客户端执行此操作,方法是将正常时间戳发送到客户端,例如,对于Web,有一个jquery插件可以执行此操作: jquery-timeago

我建议在客户端执行此操作,因为客户端可以根据需要刷新它(例如,当页面保持打开更长时间时)。 如果需要,用户也可以使用绝对数据。

我更改了镰刀提供的代码,以增加月数,周数和年数的补贴。

function agoTime($time) {
$delta = time() - $time;

if ($delta < 60) {
  return 'less than a minute ago.';
 } else if ($delta < 120) {
return 'about a minute ago.';
 } else if ($delta < (45 * 60)) {
return floor($delta / 60) . ' minutes ago.';
 } else if ($delta < (90 * 60)) {
return 'about an hour ago.';
 } else if ($delta < (24 * 60 * 60)) {
return 'about ' . floor($delta / 3600) . ' hours ago.';
 } else if ($delta < (48 * 60 * 60)) {
return '1 day ago.';
 } else if ($delta < (11 * 24 * 60 * 60)) {
return 'about a week ago.';
 } else if ($delta < (30 * 24 * 60 * 60)) {
return 'about ' .floor($delta / 604800) . ' weeks ago.';
 } else if ($delta < (45 * 24 * 60 * 60)) {
return 'more than a month ago.';
 } else if ($delta < (365 * 24 * 60 * 60)) {
return 'about ' .floor($delta / 2592000) . ' months ago.';
 } else if ($delta < (550 * 24 * 60 * 60)) {
return 'more than a year ago.';
 } else {
return 'about ' .floor($delta / 31536000) . ' years ago.';
 }

我的建议是用PHP计算差异。

你可以做的是在你的数据库中有一个时间戳(考虑一个中性时区),然后进行查询,以便你调度任何适合你的间隔(IE时间戳 - 现在()<N),其中N是你的时间间隔。

此时,您使用PHP将事件日期转换为现在的差异(也可以是动态客户端 - IE Javascript - 用于最近的条目,因此包含秒数/分钟,因为ebay使用到期操作)。

我不会在数据库中放置逻辑的原因是因为我认为这样的数据是依赖于应用程序的,而不是依赖于数据库的 - IE有一天你可能想要以另一种方式显示时间差异,而db不可能是最通用的你手边的工具 - 不一定是因为性能(我认为无论如何影响可以忽略不计)。

在从数据库中提取数据之后,几乎肯定最好是作为独立函数执行。

当然,它会产生一些小的开销......但是当将这些开销与你正在做的其他所有内容的开销进行比较时,我预计它甚至无法测量(除非你的算法非常低效) )。

此外,由于数据库通常是瓶颈,而不是应用服务器的CPU,因此在应用服务器而不是数据库上进行此类工作通常是个好主意。

几乎没有任何东西几乎没有任何东西。 别担心。 一个简单的检查如下:

if time > day
  write time.in_days + " days"
if time > hour
  write time.in_hours + " hours"
if time > minute
  write time.in_minutes + " minute"
if time > second
  write time.in_seconds + " seconds"
if time > millisecond
  write time.in_seconds + " milliseconds"

只需要几个时钟周期。 您将有30亿个时钟周期可供使用,因此对此类功能的100次调用将达到毫秒级的计算工作量。

在sql中,由于语言的原因,计算将花费您构建时间。 我的选择是php或javascript。 我也听说过这个问题的jquery解决方案。 Javascript会将计算成本完全按给客户端。

  1. 从SQL获取时间戳,
  2. 使用简单的减法来获得秒的差异
  3. 你可以实现一个简单的Ordo log(n)函数而不是Ordo n来获得文本游戏中时光倒流,如下所示:
function niceTime($difference) {
  if ($difference > 86400)
    if ($difference > 2592000)
      if ($difference > 30758400) {
        $time = round($difference / 30758400);
        $unit = 'year';
      } else {
        $time = round($difference / 2592000);
        $unit = 'month';
      }
    else
      if ($difference > 604800) {
        $time = round($difference / 604800);
         $unit = 'week';
      } else {
        $time = round($difference / 86400);
        $unit = 'day';
      }
  else
    if ($difference > 900)
      if ($difference > 3600) {
        $time = round($difference / 3600);
        $unit = 'hour';
      } else {
        $time = round($difference / 900);
        $unit = 'quarter';
      }
    else
      if ($difference > 60) {
        $time = round($difference / 60);
        $unit = 'minute';
      } else {
        $time = round($difference);
        $unit = 'second';
      }
  return $time . ' ' . $unit . ($time != 1 ? 's' : '') . ' ago';
}

这里的想法是你不应该通过八个步骤来发现给定的差异确实是最坏的情况(超过一年)。 相反,你每次都将你的选项分成两半,你将在三次比较中始终达到“正确”的时间。

在最糟糕的情况下,您有一个包含100,000条评论的页面,这些评论都是两年之久,这会将比较次数从800.000减少到300.000,这是显而易见的。 ;-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM