2010-03-22 79 views
9

我有一個cron作業,更新數據庫中的大量行。有些行是新的,因此插入,有些是現有的更新,因此更新。MySQL:使用插入和更新而不是插入重複鍵更新會更快嗎?

我用重複鍵更新插入整個數據並把它在一個調用來完成。

可是 - 我真的知道哪些行是新的和更新,所以我還可以做的插入和更新seperately。

將分離該插入和更新具有優勢,在性能方面?這背後的機制是什麼?

謝謝!

+0

我會發出一個刪除知行的,然後因爲他們是我再次插入。只有當您沒有影響其他表格的觸發器或外鍵時纔有效。 – Pentium10 2010-03-22 21:39:49

+0

@Kevin Crowell我不理解你。我只在他沒有的時候才提到這個作品。 – Pentium10 2010-03-22 22:14:49

+0

也將使用「替換」 - http://dev.mysql.com/doc/refman/5.1/en/replace.html – CheeseConQueso 2010-03-23 22:53:44

回答

4

你說

其實,我知道這行是新的和更新,所以我還可以做的插入和更新seperately。

如果你知道,沒有擊中即插入的,哪些是更新數據庫,然後運行正確的語句是比執行INSERT更快... ON DUPLICATE KEY ...

的插入都將不要更快; UPDATE會更快,因爲您不必首先嚐試INSERT。

0

這要看存儲引擎使用的,MyISAM的是在選擇和插入,因爲它可以做他們同時很不錯,但它鎖定了整個表的時候寫了這麼不更新那麼好。您如何嘗試對其進行基準測試,並找出哪種方法需要更長的時間?

0

從性能的角度來看,不同的是在語句的數量 - 在內存中的數據集去在網絡和解析查詢是什麼正在大多數的時間,這就是爲什麼有它在單個語句有助於提高性能。既然你知道哪些需要插入vs更新,我不相信你會看到任何性能差異。如果Update使用WHERE語句來記錄要更新的記錄的ID,則應該看不到性能差異。

0

您是否在爲每條記錄使用個別語句?您可能需要查看批量更新的加載數據infile。上次嘗試時我們獲得了一些表現(一年)。

3

在使用ON DUPLICATE密鑰更新我的測試是在比使用插入/更新慢的平均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"; 
    ?> 

ON DUPLICATE KEY UPDATE(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"; 
?> 
2

我得到另一個完全不同的結果。 INSERT ON DUPLICATE比UPATE快!

MySQL版本

innodb_version 5.6。13

PROTOCOL_VERSION 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; 

@更新= 2013-09-12 17:32:27

@ updateend = 2013年9月12日17時33分01秒

@ updatediff = 34

@ =的insertUpdate 2013年9月12日17時32分00秒

@insertdate_end = 2013年9月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; 

測試功能

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