Хитрый пакетный запрос MySQL - PullRequest
2 голосов
/ 18 января 2012

У меня есть база данных событий, которая обновляется каждую ночь.Одно событие содержит информацию в трех (или более) таблицах.Недавно объем обновлений привел к тому, что мой движок MySQL стал очень медленным до такой степени, что мои другие запросы зависали во время вставки новых событий.Чтобы ускорить процесс, я хочу сделать серию пакетных запросов вместо того, чтобы выполнять каждый из них по отдельности, что, как мне кажется, является большой частью накладных расходов.

Проблема заключается в том, что данные распределяются подля нескольких таблиц это то, что я должен сделать, чтобы вставить одно событие:

   (in Mysql) INSERT INTO 'locations' (...) VALUES (...) ON DUPLICATE KEY UPDATE ...
   (in php get the last inserted id into variable $locationID)
   (in Mysql) INSERT INTO 'event_info' (...) VALUES ($locationID, ...) ON DUPLICATE KEY UPDATE...
   (in php get the last inserted id into variable $eventID)
   (in Mysql) INSERT INTO 'event_times' (...) VALUES ($eventID, ...) ON DUPLICATE KEY UPDATE...

Я не ищу помощи в разработке таблиц, но, как вы можете видеть, чтобы вставить одно событие, требуется как минимум тривставляет , каждый из которых зависит от получения идентификатора от предыдущего. Вот почему я не знал, с чего начать, чтобы превратить это в пакетный запрос.Любая помощь по проектированию этого процесса в пакетный запрос была бы потрясающей, спасибо!

РЕДАКТИРОВАТЬ: Возможно, я уже имел информацию о местоположении или о событии ранее, и именно поэтому ON DUPLICATE KEY UPDATEчасть есть, так что если она уже была в базе данных, я получаю старый идентификатор.Я не знаю до вставки, если это новые данные или если они уже существуют в базе данных.(из-за этого, если я не неправильно понял, я не могу делать вещи, которые предварительно распределяют идентификаторы, так как каждый раз это принимает новый идентификатор.)

Ответы [ 2 ]

2 голосов
/ 18 января 2012

Не знаю подробностей MySQL, но любая уважающая себя СУБД имеет так называемые «последовательности» сущностей, которые предназначены для использования в качестве источника уникальных значений, подходящих для первичных ключей таблиц.

Ниже приведен подход к решению вашей проблемы с использованием последовательностей, с которыми я сталкивался несколько раз. Использование псевдокода:

  1. Начать транзакцию
  2. Выберите 3 следующих значения из некоторой последовательности. Опять же, любая уважающая себя СУБД гарантирует, что каждый запрос «следующего значения последовательности» будет возвращать уникальное значение, пригодное для использования в качестве первичного ключа. Три выбранных значения будут для первичных ключей новых записей в locations, event_info, event_times;
  3. Выполните INSERT INTO locations, используя значение с 1-го шага;
  4. Выполните INSERT INTO event_info, используя значения с 1-го шага;
  5. Выполните INSERT INTO event_times, используя значения с 1-го шага;
  6. COMMIT транзакция, если все было хорошо. В противном случае, ROLLBACK транзакция.

Необходимо сделать все INSERT в одной транзакции. Для дальнейших улучшений вы можете группировать ваши запросы.

ОБНОВЛЕНИЕ В соответствии с вашим требованием о возможном предварительном существовании данных до INSERT с

Если ваши входящие обновления всегда содержат полный набор данных: это location, event_info и event_times: тогда используйте вышеуказанный подход и просто удалите старые экземпляры записей в таблицах. Это предполагает, что вы можете SELECT старых экземпляров, используя некоторые данные, отличные от первичного ключа (это данные, называемые первичным ключом на уровне домена). Не забудьте сделать DELETE в одной транзакции!

2 голосов
/ 18 января 2012

Не используйте автоинкрементные столбцы - предварительно вставьте ваши ссылочные идентификаторы перед вставкой.Таким образом, вы можете использовать массовую вставку и удалить зависимость.

Обновление:

  1. Выбрать любые существующие идентификаторы из базы данных (в идеале один выбор для всех известных данных).

  2. Обогащение данных для вставки любым известным идентификатором.(рассчитайте ключ для каждого элемента, который будет соответствовать первичному ключу для вашей таблицы в базе данных, используйте его для обновления элемента с помощью идентификатора из базы данных) - вы хотите в конечном итоге разбить данные на элементы, о которых вы знаете вбазы данных, и, следовательно, имеют известный идентификатор - и данные, которых нет в базе данных, и, следовательно, требуется распределение ключа.Я предполагаю, что у вашей таблицы есть первичный ключ, а не просто идентификатор - иначе как база данных узнает, что у вас уже есть данные в базе данных.

  3. Назначьте новые идентификаторы длялюбые записи без идентификатора.

  4. массовая замена данных в базе данных (вставка нескольких строк одним оператором).

...