Mysqli num_rows检查慢?

时间:2015-02-28 14:50:39

标签: php mysql database mysqli

我有一个c ++程序,它将日志POST发送到我的服务器并将其存储在数据库中,问题是在插入新行之前检查重复项是不行的,我认为程序发送POST速度非常快POSTS与服务器之间没有延迟,因此Mysqli无法处理这个问题,服务器客户端是否有任何解决方案?也许锁定行或什么?

$date = date('Y-m-d', time());
$prep_select_qa = 'SELECT * from `logs` WHERE `guid` = ? AND `error_code` = ? AND `date_create` = ?';
$select_qa = $db->prepare($prep_select_qa);
$select_qa->bind_param('sss', $_POST['guid'], $_POST['error_code'], $date);
$select_qa->execute();
$select_qa->store_result();
$num_rows = $select_qa->num_rows;
if($num_rows == 0)
{
    $prep_insert_qa = 'INSERT INTO `logs` (`type`, `guid`, `sent_by`, `class_and_method`, `api_method`, `error_code`, `error_text`, `date_create`) VALUES (?,?,?,?,?,?,?,?)';
    $insert_qa = $db->prepare($prep_insert_qa);
    $insert_qa->bind_param('ssssssss', $new, $_POST['guid'], $_POST['sentBy'], $_POST['classAndMethodName'], $_POST['APImethod'], $_POST['ErrorCode'], $_POST['ErrorText'], $date);
    $insert_qa->execute();
    $insert_qa->store_result();

}

2 个答案:

答案 0 :(得分:0)

首先,您的问题的答案是您正在检索所有行以计算它们。据推测,这需要读取表中的所有数据并返回其中的一些数据(除非您有索引)。更快的方法是检查此查询返回的值:

SELECT count(*)
FROM `logs`
WHERE `guid` = ? AND `error_code` = ? AND `date_create` = ?';

更快的方法不是计算,而是确定是否存在任何行:

SELECT EXISTS (SELECT 1
               FROM `logs`
               WHERE `guid` = ? AND `error_code` = ? AND `date_create` = ?'
              )

如果行存在则返回1,否则返回0。上述两个查询和您的原始查询都将受益于guid, error_code, date_create上的索引。

在实践中,您应该遵循Marvin的建议并使用唯一索引。这意味着数据库通过唯一索引而不是应用程序进行检查。一个非常重要的原因是竞争条件。如果两个用户同时插入同一行,则两者都可以执行if语句,发现表中没有匹配的行,然后插入重复的行。

答案 1 :(得分:0)

SELECT方案必须包含在BEGIN ... COMMIT事务中并对其进行FOR UPDATE。否则,其他一些连接可能会漏入并打败您的支票。

相反,尝试在单个原子指令中执行此操作:

一旦你有一个可以防止重复的INDEX ......

INSERT IGNORE - 如果它是一个副本,则默默无闻。

INSERT ... ON DUPLICATE KEY UPDATE - 允许您在尝试插入dup时更改内容。

此外,INSERT解决方案会更快(这是您最初的问题)。