Nir*_*Nir 12 mysql performance
我有一个cron作业,它可以更新数据库中的大量行.一些行是新的,因此插入,一些是现有的行的更新,因此更新.
我在整个数据的重复密钥更新上使用insert,并在一次调用中完成.
但是 - 我实际上知道哪些行是新的,哪些是更新的,所以我也可以分别进行插入和更新.
分离插入和更新在性能方面有优势吗?这有什么机制?
谢谢!
你说
我实际上知道哪些行是新的,哪些是更新的,所以我也可以分别进行插入和更新.
如果你知道没有命中INSERT的数据库和UPDATEs,那么运行正确的语句必须比执行INSERT更快... ON DUPLICATE KEY ...
INSERT将不会更快; UPDATE会更快,因为您不必先尝试INSERT.
在我的测试中使用ON DUPLICATE KEY UPDATE平均比使用Insert/Update慢1.3倍.这是我的测试:
INSERT/UPDATE(54.07秒)
<?php
$mtime = microtime();
$mtime = explode(" ",$mtime);
$mtime = $mtime[1] + $mtime[0];
$starttime = $mtime;
?>
<?php
set_time_limit(0);
$con = mysql_connect('localhost', 'root', '');
mysql_select_db('test');
for ($i = 1; $i <= 1000; $i = $i + 2)
{
mysql_query("
INSERT INTO users
VALUES(NULL, 'username{$i}', 'email.{$i}', 'password{$i}')
");
}
for ($i = 1; $i <= 1000; $i++)
{
if ($i % 2 == 0)
{
mysql_query("
INSERT INTO users
VALUES(NULL, 'username{$i}', 'email.{$i}', 'password{$i}')
");
}
else
{
mysql_query("
UPDATE users
SET (username = 'username{$i}', email = 'email{$i}', password = 'password{$i}')
");
}
}
?>
<?php
$mtime = microtime();
$mtime = explode(" ",$mtime);
$mtime = $mtime[1] + $mtime[0];
$endtime = $mtime;
$totaltime = ($endtime - $starttime);
echo "This page was created in ".$totaltime." seconds";
?>
Run Code Online (Sandbox Code Playgroud)
在重复的关键更新(70.4秒)
<?php
$mtime = microtime();
$mtime = explode(" ",$mtime);
$mtime = $mtime[1] + $mtime[0];
$starttime = $mtime;
?>
<?php
set_time_limit(0);
$con = mysql_connect('localhost', 'root', '');
mysql_select_db('test');
for ($i = 1; $i <= 1000; $i = $i + 2)
{
mysql_query("
INSERT INTO users
VALUES(NULL, 'username{$i}', 'email.{$i}', 'password{$i}')
");
}
for ($i = 1; $i <= 1000; $i++)
{
mysql_query("
INSERT INTO users
VALUES({$i}, 'username{$i}', 'email.{$i}', 'password{$i}')
ON DUPLICATE KEY UPDATE
username = 'username{$i}', email = 'email{$i}', password = 'password{$i}'
");
}
?>
<?php
$mtime = microtime();
$mtime = explode(" ",$mtime);
$mtime = $mtime[1] + $mtime[0];
$endtime = $mtime;
$totaltime = ($endtime - $starttime);
echo "This page was created in ".$totaltime." seconds";
?>
Run Code Online (Sandbox Code Playgroud)
我得到了另一个完全不同的结果。INSERT ON DUPLICATE 比 UPATE 快!!!
MySQL 版本
innodb_version 5.6.13
协议_版本 10
版本 5.6.13-企业-商业-高级
version_compile_machine x86_64
version_compile_os osx10.7
结果
SELECT udf_CreateCounterID(0,CURRENT_DATE);
SELECT @update, @updateend, @updatediff, @insertupdate, @insertupdate_end, @insertupdatediff, @keyval, @countlmt;
Run Code Online (Sandbox Code Playgroud)
@更新=2013-09-12 17:32:27
@updateend=2013-09-12 17:33:01
@updatediff=34
@insertupdate=2013-09-12 17:32:00
@insertdate_end=2013-09-12 17:32:27
@insertupdatediff=27
@keyval=13
@countlmt=1000000
桌子
CREATE TABLE `sys_CounterID` (`exch_year` int(11) NOT NULL,
`nextID` int(11) NOT NULL,
PRIMARY KEY (`exch_year`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Run Code Online (Sandbox Code Playgroud)
测试功能
CREATE DEFINER=`root`@`localhost` FUNCTION `udf_CreateCounterID`(exchID SMALLINT, listyear DATE) RETURNS int(10) unsigned
BEGIN
DECLARE keyvalue INT UNSIGNED DEFAULT 0;
SET @countlmt = 1000000;
SET keyvalue = ((exchID % 512) << 9 ) + EXTRACT(YEAR FROM listyear) % 100;
SET @keyval = keyvalue;
SET @retVal = 0;
SET @count = @countlmt;
SET @insertupdate = SYSDATE();
WHILE @count > 0 DO
INSERT INTO `sys_CounterID`(`exch_year`,nextID)
VALUE( keyvalue, 1)
ON DUPLICATE KEY UPDATE
nextID = (@retVal := nextID + 1);
SET @count = @count - 1;
END WHILE;
SET @insertupdate_end = SYSDATE();
SET @insertupdatediff = TIMESTAMPDIFF(SECOND, @insertupdate,@insertupdate_end);
SET @count = @countlmt;
SET @update = SYSDATE();
WHILE @count > 0 DO
UPDATE sys_CounterID
SET nextID = (@retVal := nextID + 1)
WHERE exch_year = keyvalue;
SET @count = @count - 1;
END WHILE;
SET @updateend = SYSDATE();
SET @updatediff = TIMESTAMPDIFF(SECOND, @update,@updateend);
RETURN @retVal;
END
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11025 次 |
| 最近记录: |