首页 > 解决方案 > 性能:使用 try(语句)和 catch(输出错误)而不是检查电子邮件是否已经存在

问题描述

很多时候,当电子邮件等值已经存在时,我需要阻止查询被执行。

到目前为止,我搜索了这样的值:

$checkemailexist = $X['db']->prepare("SELECT uid FROM userdata WHERE uid = :uid LIMIT 1");
$checkemailexist->execute(array(
':uid'=>$uid
));

if(empty($checkemailexist)){
   INSERT QUERY ..
}

...

在具有许多行的大型数据库上的问题,即使在 varchar 上进行字符串搜索也可能需要大量的性能和时间。

所以我使 uid 列独一无二并尝试了类似的方法:

try{    
    $insertuser = $X['dbh']->prepare("
    INSERT INTO user (uid) VALUES (:uid) 
    ");

    $insertuser->execute(array(
    ':uid'=> $mail
    ));

} catch (PDOException $e) {
        header("Location: ...");
        exit(); 
}


它工作正常,但性能会更差吗?

标签: phpperformancepdodatabase-performancequery-performance

解决方案


将 uid 列设为 [唯一] 索引后,您的所有查询都变得更快了。两个查询,无论是 SELECT 还是 INSERT 都必须检查索引,并且它们都需要相同的时间来执行。

向用于搜索的列添加索引是您问题的真正答案。至于是使用选择查询还是在插入期间捕获异常是个人喜好问题。

但是,您的第二个示例是相当错误的。您不应该以相同的方式处理每个 PDOException,而应该只处理与此案例相关的特定异常,如我的PDO 教程中所示。

最好的方法是保留唯一索引,但在查询中添加关键字 IGNORE,然后检查受影响的行数

$insertuser = $X['dbh']->prepare("INSERT IGNORE INTO user (uid) VALUES (:uid)");
$insertuser->execute(['uid'=> $mail]));
if (!$insertuser->numRows()) {
    header("Location: ...");
    exit(); 
} 

添加 IGNORE 将抑制唯一索引错误,您将能够通过简单地检查受影响的行数来检查这样的值是否已经存在


推荐阅读