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

Performance: Using try (statement) and catch (output error) instead of checking if email already exist

我经常需要阻止在电子邮件之类的值已经存在时执行查询。

直到现在我搜索了这样的值:

$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(); 
}


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

将 uid 列设为 [唯一] 索引后,您 所有 查询速度更快。 SELECT 或 INSERT 两个查询都必须检查索引,并且 同时 执行它们。

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

但是,你的第二个例子是错误的。您不应该以相同的方式处理每个 PDOException,而应该只处理与这种情况相关的特定异常,如我的 PDO tutorial.

中所示

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

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

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