Все наступне стосується InnoDB.
Я вважаю, що важливість швидкості застосування трьох різних методів є важливою.
Існує 3 методи:
- ВСТАВКА: ВСТАВИТЬСЯ НА ВКЛЮЧЕНОЮ ДОДАТКОВОЮ КЛЮЧНОЮ ОНОВЛЕННЯ
- ТРАНЗАКЦІЯ: Де ви робите оновлення для кожного запису в рамках транзакції
- СЛУЧАЙ: У якому випадку ви перебуваєте у випадку, коли для кожного іншого запису в межах оновлення
Я щойно це перевірив, і метод INSERT був для мене на 6,7 рази швидшим, ніж метод TRANSACTION. Я спробував набір як 3000, так і 30 000 рядів.
Метод TRANSACTION все ще повинен запускати кожен окремо запит, який вимагає часу, хоча він виконує результати в пам'яті чи щось під час виконання. Метод TRANSACTION також досить дорогий як в реплікації, так і в журналах запитів.
Ще гірше, що метод CASE був на 41,1 разів повільніше, ніж метод INSERT з 30000 записами (на 6,1 рази повільніше, ніж ТРАНЗАКЦІЯ). І в 75 разів повільніше в MyISAM. Методи INSERT і CASE побилися навіть при ~ 1000 записів. Навіть при 100 записах метод CASE БАРЕШЕ швидший.
Тому в цілому я вважаю, що метод INSERT є найкращим і найпростішим у використанні. Запити менші та простіші для читання та займають лише 1 запит дій. Це стосується і InnoDB, і MyISAM.
Бонусні речі:
Рішення завдання не за замовчуванням поля INSERT, щоб тимчасово відключити відповідні режими SQL: SET SESSION sql_mode=REPLACE(REPLACE(@@SESSION.sql_mode,"STRICT_TRANS_TABLES",""),"STRICT_ALL_TABLES","")
. Не забудьте зберегти sql_mode
перше, якщо плануєте його повернути.
Що стосується інших коментарів, які я бачив, що кажуть, що auto_increment збільшується за допомогою методу INSERT, здається, це стосується InnoDB, але не MyISAM.
Код для запуску тестів такий. Він також виводить .SQL файли, щоб видалити накладні перекладачі php
<?
//Variables
$NumRows=30000;
//These 2 functions need to be filled in
function InitSQL()
{
}
function RunSQLQuery($Q)
{
}
//Run the 3 tests
InitSQL();
for($i=0;$i<3;$i++)
RunTest($i, $NumRows);
function RunTest($TestNum, $NumRows)
{
$TheQueries=Array();
$DoQuery=function($Query) use (&$TheQueries)
{
RunSQLQuery($Query);
$TheQueries[]=$Query;
};
$TableName='Test';
$DoQuery('DROP TABLE IF EXISTS '.$TableName);
$DoQuery('CREATE TABLE '.$TableName.' (i1 int NOT NULL AUTO_INCREMENT, i2 int NOT NULL, primary key (i1)) ENGINE=InnoDB');
$DoQuery('INSERT INTO '.$TableName.' (i2) VALUES ('.implode('), (', range(2, $NumRows+1)).')');
if($TestNum==0)
{
$TestName='Transaction';
$Start=microtime(true);
$DoQuery('START TRANSACTION');
for($i=1;$i<=$NumRows;$i++)
$DoQuery('UPDATE '.$TableName.' SET i2='.(($i+5)*1000).' WHERE i1='.$i);
$DoQuery('COMMIT');
}
if($TestNum==1)
{
$TestName='Insert';
$Query=Array();
for($i=1;$i<=$NumRows;$i++)
$Query[]=sprintf("(%d,%d)", $i, (($i+5)*1000));
$Start=microtime(true);
$DoQuery('INSERT INTO '.$TableName.' VALUES '.implode(', ', $Query).' ON DUPLICATE KEY UPDATE i2=VALUES(i2)');
}
if($TestNum==2)
{
$TestName='Case';
$Query=Array();
for($i=1;$i<=$NumRows;$i++)
$Query[]=sprintf('WHEN %d THEN %d', $i, (($i+5)*1000));
$Start=microtime(true);
$DoQuery("UPDATE $TableName SET i2=CASE i1\n".implode("\n", $Query)."\nEND\nWHERE i1 IN (".implode(',', range(1, $NumRows)).')');
}
print "$TestName: ".(microtime(true)-$Start)."<br>\n";
file_put_contents("./$TestName.sql", implode(";\n", $TheQueries).';');
}