4

I need to populate a MySQL table with random SHA-1 hash values, generated by PHP function. I`m trying to optimize the insert by splitting it in chunks of 10000. My question is: Is the following approach efficient? Here is the code.

//MySQL server connection routines are above this point
if ($select_db) {
$time_start = microtime(true);
//query
$query = 'INSERT INTO sha1_hash (sha1_hash) VALUES ';
for ($i=1; $i<1000001; $i++) {
 $query .= "('".sha1(genRandomString(8))."'),";
    $count++;
    if ($count ==10000) {
    //result
 $result = mysql_query(rtrim($query,',')) or die ('Query error:'.mysql_error());
    if ($result) mysql_free_result($result);
    $count = 0;
    }
}

$time_end = microtime(true);
echo '<br/>'. ($time_end - $time_start);
}

//function to generate random string
function genRandomString($length)
{
$charset='abcdefghijklmnopqrstuvwxyz0123456789';
$count = strlen($charset);
 while ($length--) {
  $str .= $charset[mt_rand(0, $count-1)];
 }
return $str;
}

EDIT: The $time_start and $time_end variables are ONLY for performance testing purposes. Also the MySQL table has two fields only: ID int(11) UNSIGNED NOT NULL AUTO_INCREMENT and sha1_hash varchar(48) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, the engine is MyISAM EDIT2: The computer hardware point of view is not related to the question.

4

1 に答える 1

4

挿入のたびにインデックスが更新されるため、通常、挿入は大きなバッチで行われます。バッチ処理を使用すると、多くのレコードを挿入してから、各行の後でなく、最後に 1 回だけインデックスを更新できます。

ただし、自動インクリメント主キー インデックスの場合、新しい行を追加するためにもインデックスを拡張する必要があるため、他のインデックスがないため、そこには何も保存されません。

バッチ処理により、クエリの解析とロックのオーバーヘッドも節約されます。ただし、パラメーター化されたクエリ (PDO) の使用を検討することもできます。

PDO のパラメーター化されたクエリを使用して一度に 1 つのレコードを挿入することも非常に高速です。MySQL はクエリを 1 回だけ解析する必要があり、それ以降は行データの低オーバーヘッド バイナリ転送を使用するからです。

で挿入を開始する前に、テーブルをロックすることがありますLOCK TABLES。これにより、テーブル ロックのオーバーヘッドが少し節約されます。

また、SHA1 は常に 40 文字の 16 進数でエンコードされた ASCII 値であるため、CHAR(40)代わりにVARCHAR(). これにより、作業も高速化されます。また、SHA1 列がインデックス化されている場合は、UTF8 の代わりにシングルバイト文字セットを使用して、インデックスのサイズを縮小し、処理を高速化します。

于 2012-05-07T14:36:53.213 に答える