現在、私はTokuDBをテストしており、とても感心しています。現時点では、1秒あたりのインサート数は、2つの同時実行ジョブを実行して1秒間に50,000を超えてピークに達しています。平均インサート速度は1秒あたり38.000〜42.000インサートです。tokudbで50.000以上の挿入を行うにはどうすればいいですか?
私は、今のところ12億の計算された行を挿入し、近い将来には約60億を挿入する必要があるので、さらに高い100.000インサート/秒を実行したいと思います。
- ハードウェア:4GBのRAMを持つVPS、150ギガバイトSSD、2つのコア:インテルのWestmere E56xx/L56xx/X56xx(Nehalemの私はこの:-)
私の現在の設定を達成する方法についていくつかのアドバイスをしたいと思います-C)2.59GHzのCPU
- ディスクのマウントオプション:デフォルト、noatimeオプション
- OS:CentOSの6.8 64ビット
- データベース:Perconaサーバー5.7.14-8
のmy.cnfの設定:
# TokuDB #
tokudb_cache_size = 2G
tokudb_commit_sync = 0
tokudb_fsync_log_period = 1000
TokuDBテーブルのレイアウト:
CREATE TABLE `t1` (
`id` int(15) NOT NULL AUTO_INCREMENT,
`m_id` int(11) NOT NULL,
`c1` decimal(6,2) DEFAULT NULL,
`c2` decimal(6,2) DEFAULT NULL,
`c3` decimal(6,2) DEFAULT NULL,
`c4` decimal(6,2) DEFAULT NULL,
`c5` decimal(6,2) DEFAULT NULL,
`c6` decimal(6,2) DEFAULT NULL,
`c7` decimal(6,2) DEFAULT NULL,
`factor` decimal(4,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=latin1
CREATE TABLE `t2` (
`id` int(15) NOT NULL AUTO_INCREMENT,
`v_id` int(15) NOT NULL,
`pid` int(11) DEFAULT NULL,
`amount` decimal(6,2) DEFAULT NULL,
`unit` int(1) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=TokuDB DEFAULT CHARSET=latin1
私は、他のすべてのインデックス 主キー索引を使用していないという事実を認識してね。これは、鍵が の挿入時に負の時間の影響があるためです。各テーブルのクラスタキーは、挿入ジョブの末尾の に作成されます。
追加MySQLのコマンドラインオプション:
SET unique_checks=OFF;
誰かが、これは非常に高く評価されるだろうか、その後を知っているだろう場合はどういうわけか、私は=現在UNIQUE_CHECKS(.. my.cnfの中でこれを取得することはできませんよmy.cnfの変数が分からないためにMySQLが起動しないようにします)。
SQLステートメントは、15.000のバッチでグループ化されています。 PHPスクリプトは、SQL文を生成し、MySQLサーバにmysqli_multiqueryを経由して、クエリを送信します:SQLのINSERT文の
<?PHP
foreach (generateCombinations($Arr) as $c) {
$QueryBatch[] = "insert into t1 values (NULL"
. ", " . $record->id
. ", " . rand(1, 35)
. ", " . rand(1, 140)
. ", " . rand(1, 20)
. ", NULL"
. ", " . rand(1, 14)
. ", " . rand(1, 300)
. ", " . rand(1, 4)
. ", NULL);";
$QueryBatch[] = "SET @t1id = LAST_INSERT_ID();";
$cntBatch++;
$pquery = array();
foreach ($c as $key => $pid){
if (is_null($pid))
continue;
$pquery[] = "(NULL, @t1id, " . $pid . ", " . rand(1, 800) . ", 0)";
$cntBatch++;
}
$QueryBatch[] = "insert into t2 values " . implode(',', $pquery) . ";";
if ($cntBatch > 15000) {
$query = implode($QueryBatch);
if ($mysqli->multi_query($query)){
while ($mysqli->next_result()) {;}
} else {
printf("Errormessage: %s\n", $mysqli->error);
echo $query . "\n";
}
$cntBatch = 0;
unset($QueryBatch);
}
}
?>
例:それは私だったら
insert into t1 values (NULL, 1 , 30, 100, 15, NULL, 10, 250, 2, NULL);
SET @t1id = LAST_INSERT_ID();
insert into t2 values (NULL, @t1id, 1, 750, 0),(NULL, @t1id, 1, 600, 0),(NULL, @t1id, 1, 500, 0),(NULL, @t1id, 1, 400, 0),(NULL, @t1id, 1, 300, 0),(NULL, @t1id, 1, 200, 0),(NULL, @t1id, 1, 100, 0);
insert into t1 values (NULL, 2 , 25, 95, 14, NULL, 11, 200, 3, NULL);
SET @t1id = LAST_INSERT_ID();
insert into t2 values (NULL, @t1id, 1, 600, 0),(NULL, @t1id, 1, 100, 0),(NULL, @t1id, 1, 300, 0),(NULL, @t1id, 1, 443, 0),(NULL, @t1id, 1, 521, 0),(NULL, @t1id, 1, 213, 0),(NULL, @t1id, 1, 433, 0);
[.. At least 14982 more..]
スペンサー7593、あなたの詳細な答えをありがとう!私はあなたが言っていることを理解していることを理解していますが、事柄です;関連するt2の対応するレコードのt1のIDを知る必要があります。基本的に1つのジョブだけがレコードを作成するので、自動インクリメントを削除してIDを作成することをお勧めします – Robbert
AUTO_INCREMENTカラムに値を指定することができますAUTO_INCREMENTを削除したり無効にしたりすることなく、NULL値を指定してAUTO_INCREMENTの動作を取得します。 'id'値を評価し、両方の値に' t1'と 't2'の両方にその値を与えてください。これをスピードアップするために私がやることは... SQL文の数とCOMMITの数を減らすことです。 – spencer7593
InnoDBでは、auto_incrementの動作を設定して*連続* auto_increment値を取得します。したがって、複数行の挿入は、最初の行がLAST_INSERT_ID()+ 0であり、2行目がLAST_INSERT_ID()+ 1までLAST_INSERT_ID()+ ROW_COUNT()まで挿入されていることがわかります。AUTO_INCREMENT値を使用しなければならない場合は、挿入を 't1'(mutli-row insert)、' SELECT LAST_INSERT_ID()INTO @ lid'にバッチし、次に 't2'への挿入は' @ lid + 0 '挿入された第1のt1行に関する行については' @ lid + 1 'が挿入される。 (私の注意は、tokudbのAUTO_INCREMENTの動作がInnoDBと同じであるかどうか分かりません) – spencer7593