计算年龄:PHP vs MySQL,哪种方法更好?

时间:2018-07-28 04:32:20

标签: php mysql sql optimization query-optimization

我在MySQL数据库中大约有500,000条个人资料记录,其中包含一个生日日期列(dob)。由于必须获得每个配置文件的年龄,因此我需要动态地计算它,可以通过PHP (date_diff(date_create($dob), date_create('today'))->y)或SQL ('SELECT TIMESTAMPDIFF(YEAR, dob, CURDATE()) AS age')进行计算。 两者中哪个更快或更优选,特别是如果我有成千上万的行?

3 个答案:

答案 0 :(得分:3)

通常,最好的方法是在服务器上进行此类计算。

理想的方法是使用生成的列。自MySQL 5.7.5起,该功能已可用,并表示为:

alter table t add age unsigned as 
    (TIMESTAMPDIFF(YEAR, dob, CURDATE()));

A,您只能将确定性函数用于生成的列。 curdate()now()不确定,因为每次调用它们的值都会改变。

下一个最好的方法是使用视图:

create view v_t as
    select t.*,
           TIMESTAMPDIFF(YEAR, dob, CURDATE())
    from t;

然后,当您查询视图时,将得到age。无论在哪里查询,都是如此。到处都是相同的逻辑。

在服务器上进行计算的唯一警告是它使用服务器时间,而不是本地应用程序时间。如果这是一个问题,那么这是在本地进行计算的有力论据。

答案 1 :(得分:0)

这是一个测试:

创建一个随机日期为100K的表格

drop table if exists birthdays;
create table birthdays (
    id int auto_increment primary key,
    dob date
);
insert into birthdays (dob)
    select '1950-01-01' + interval floor(rand(1)*68*365) day as dob
    from information_schema.COLUMNS c1
       , information_schema.COLUMNS c2
       , information_schema.COLUMNS c3
    limit 100000
;

运行此PHP脚本

<?php
header('Content-type: text/plain');
$db = new PDO("mysql:host=localhost;dbname=test", "test","");

### SQL
$starttime = microtime(true);

$stmt = $db->query("SELECT id, dob, TIMESTAMPDIFF(YEAR, dob, CURDATE()) AS age FROM birthdays");
$data = $stmt->fetchAll(PDO::FETCH_OBJ);

$runtime = microtime(true) - $starttime;
echo "SQL: $runtime \n";

### PHP
$starttime = microtime(true);

$stmt = $db->query("SELECT id, dob FROM birthdays");
$data = $stmt->fetchAll(PDO::FETCH_OBJ);
foreach ($data as $row) {
    $row->age = date_diff(date_create($row->dob), date_create('today'))->y;
}

$runtime = microtime(true) - $starttime;
echo "PHP: $runtime \n";

结果:

SQL: 0.19094109535217 
PHP: 1.203684091568 

SQL解决方案似乎快了 6倍。但这不是真的。如果从这两个解决方案中删除计算年龄的代码,我们将得到类似 0.1653790473938 的信息。这意味着SQL的开销为 0.025秒,而PHP的开销为 1.038秒。因此,在此测试中,SQL的速度快40倍

注意:有更快的方法可以计算PHP的年龄。例如

$d = date('Y-m-d');
$row->age = substr($d, 0, 4) - substr($row->dob, 0, 4) - (substr($row->dob, 5) > substr($d, 5) ? 1 : 0);

快了四倍-date('Y-m-d')消耗了80%以上的时间。如果找到避免使用任何日期函数的方法,则可能会接近MySQL的性能。

答案 2 :(得分:-1)

如果要获取所有500,000条记录,则应在MySql中执行此操作,因为性能优于PHP

但是,如果要获取某些数据(例如10条记录),请使用PHP进行处理,最好处理。和性能没什么不同