निम्नलिखित में से सभी InnoDB पर लागू होते हैं।
मुझे लगता है कि 3 अलग-अलग तरीकों की गति जानना महत्वपूर्ण है।
3 विधियाँ हैं:
- INSERT: INUPERT ON DUPLICATE KEY UPDATE
- लेन-देन: जहाँ आप एक लेनदेन के भीतर प्रत्येक रिकॉर्ड के लिए एक अद्यतन करते हैं
- मामले: जिसमें आप एक मामला / जब प्रत्येक अलग रिकॉर्ड के लिए एक अद्यतन
मैंने अभी-अभी इसका परीक्षण किया था, और INSERT विधि मेरे लिए ट्रांजेक्शन विधि की तुलना में 6.7 गुना तेज थी । मैंने 3,000 और 30,000 पंक्तियों के सेट पर कोशिश की।
परिवहन विधि अभी भी प्रत्येक व्यक्तिगत क्वेरी को चलाने के लिए है, जिसमें समय लगता है, हालांकि यह निष्पादन में, या स्मृति में परिणाम को बैच देता है। परिवहन विधि भी प्रतिकृति और क्वेरी लॉग दोनों में बहुत महंगा है।
इससे भी बदतर यह मामला विधि थी 41.1x सम्मिलित करें विधि की तुलना में धीमी w / 30,000 रिकॉर्ड (6.1x लेन-देन की तुलना में धीमी)। और MyISAM में 75x धीमा। INSERT और CASE विधियाँ ~ 1,000 के रिकॉर्ड में भी टूट गईं। यहां तक कि 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 नहीं।
परीक्षण चलाने के लिए कोड इस प्रकार है। यह php दुभाषिया उपरि हटाने के लिए .SQL फाइलें भी आउटपुट करता है
<?
//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).';');
}