В настоящее время я тестирую TokuDB и очень впечатлен. На данный момент количество вставок в секунду достигло чуть более 50 000 в секунду при одновременном выполнении двух заданий. Средняя скорость вставки составляет от 38 000 до 42 000 вставок в секунду.
Я хотел бы пойти еще выше, 100 000 вставок в секунду, так как мне нужно будет вставить 1,2 миллиарда вычисляемых строк на данный момент и еще около 6 миллиардов в ближайшем будущем. Хочу посоветовать, как этого добиться :-)
Моя текущая установка:
- Аппаратное обеспечение: VPS с 4 ГБ ОЗУ, 150 ГБ SSD, 2 ядра: Intel Westmere E56xx/L56xx/X56xx (Nehalem-C), процессор 2,59 ГГц.
- Варианты монтирования диска: по умолчанию, noatime
- ОС: CentOS 6.8 64bit
- База данных: Percona Server 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;
Почему-то я не могу получить это в my.cnf.. Если кто-то знает, как это сделать, это будет очень признательно (в настоящее время unique_checks = off блокирует запуск MySQL из-за неизвестной переменной в my.cnf) .
Операторы SQL сгруппированы в пакеты по 15 000. PHP-скрипт генерирует операторы SQL и отправляет запрос через mysqli_multiquery на сервер MySQL:
<?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);
}
}
?>
Пример оператора вставки SQL:
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..]