我有一个varchar(255)
列,我将URL存储在MySQL数据库中。此列具有唯一索引。
当我的抓取工具遇到网址时,必须检查数据库以查看该网址是否已存在。如果存在,则爬网程序选择有关该条目的数据。如果它不存在,则爬网程序会添加该URL。我目前使用以下代码执行此操作:
$sql = "SELECT id, junk
FROM files
WHERE url = '$url'";
$results = $this->mysqli->query( $sql );
// the file already exists in the system
if( $results->num_rows > 0 )
{
// store data to variables
}
// the file does not exists yet... add it
else
{
// insert new file
$sql = "INSERT INTO files( url )
VALUES( '$url' )";
$results = $this->mysqli->query( $sql );
}
我意识到有很多方法可以做到这一点。我已经读过使用MySQL if / else语句可以加快速度。有人可以解释MySQL如何以不同的方式处理,以及为什么这可能会更快?我还应该测试其他替代方案吗?我的抓取工具正在进行大量的检查,加快这个过程可能会大大提高我的系统速度。
答案 0 :(得分:1)
首先,网址要比varchar(256)
长得多。
其次,因为他们长时间不想进行字符串比较,所以随着表的增长,它会变得非常慢。相反,创建一个带有哈希值的列并进行比较。
当然,您应该为哈希列编制索引。
对于实际插入,另一种方法是在哈希上放置一个唯一约束。然后盲目地进行插入,允许SQL拒绝欺骗。 (但是你必须在代码中加入一个异常处理程序,它有自己的开销。)
答案 1 :(得分:0)
考虑到不使用事务,如果WHERE条件不存在旧行,则插入新行,您可以使用:
"INSERT INTO files( url ) VALUES ( $url ) WHERE NOT EXISTS ( SELECT * FROM files WHERE url = $url );"
我无法想到同时选择和插入的“一线通用”。
答案 2 :(得分:0)
我会先插入并检查成功(affected_rows),然后选择。如果先检查,然后执行插入,则可能存在在该小时间窗口内插入URL的可能性。而且,您需要添加更多代码来处理这种情况。