Обычно, когда пользователь заходит на мой сайт, он «подписывается» примерно на ~ 50 событий одновременно, которые мы сохраняем в mapping_table
который связывает многих пользователей со многими событиями. maping_table
имеет около 50 000 записей, увеличиваясь на несколько сотен каждый день.
INSERT
эти ~ 50 строк в таблице сопоставления занимают от 10 до 20 секунд, что делает мой сайт очень медленным.
Я дошел до того, что не могу понять, как улучшить следующий PHP или SQL, чтобы уменьшить время INSERT, так как оно кажется довольно простым.
Здесь SHOW CREATE
заявление :
CREATE TABLE `mapping_table` (
`user_id` char(21) NOT NULL,
`event_id` char(21) NOT NULL,
`update_id` char(10) NOT NULL,
PRIMARY KEY (`user_id`,`event_id`),
KEY `event` (`event_id`),
CONSTRAINT `mapping_table_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users_table` (`user_id`) ON DELETE CASCADE ON UPDATE NO ACTION,
CONSTRAINT `mapping_table_ibfk_2` FOREIGN KEY (`event_id`) REFERENCES `events_table` (`event_id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Мой PHP-скрипт для вставки:
$update_id = 'RandomString';
$conn = new PDO($pdo_serv, $db_user, $db_pwd);
$stmt = $conn->prepare("INSERT INTO `mapping_table` (`user_id`, `event_id`, `update_id`)
VALUES (:uid,:eid,:upd)");
//GO THROUGH EACH USER SUBSCRIBED EVENTS AND INSERT THEM
foreach($subscribed_events AS $event) {
$stmt->bindParam(':uid', $userid);
$stmt->bindParam(':eid', $event->id);
$stmt->bindParam(':upd', $update_id);
$stmt->execute();
}
Я открыт для любых предложений.
Дополнительная информация :
Если я microtime
Я получаю в среднем от 300 мс до 1 с за каждую вставку.
Я пытался удалить UNIQUE KEY
тогда все FOREIGN KEYS
тогда все INDEXES
но это не имело никакого значения в исполнении.
Следуя комментариям на мои вопросы, я изменил свой php следующим образом: batch INSERT
:
$update_id = 'RandomString';
$conn = new PDO($pdo_serv, $db_user, $db_pwd);
$sql = "INSERT INTO `mapping_table` (`user_id`, `event_id`, `update_id`)
VALUES ";
$values = "";
//GO THROUGH EACH USER SUBSCRIBED EVENTS GENERATE VALUES STRING
foreach($subscribed_events AS $event) {
$values .= "('".$userid."','".$event->id."','".$update_id."'),"}
//Proceed batch insert
$values = rtrim($values, ",");
$sql .= $values;
$stmt = $conn->prepare($sql);
$stmt->execute();
Это уменьшило мою среднюю вставку до менее 10 мс на каждую вставленную строку (в отличие от 300 мс до 1 с на предыдущую строку). Никогда не думал, что разница будет такой большой. Благодарю.
Других решений пока нет …