Обновите большую таблицу
-
16-10-2019 - |
Вопрос
У меня есть эти два стола:
user_profile:
user_profile_id_int int primary key
user_profile_id varchar
user_activity:
user_profile_id_int int key
user_profile_id varchar
Оба поля в user_profile в порядке, но у меня нет user_profile_id_int из user_activity, и я хочу обновить ее, используя карту, которую я имею в user_profile. Я написал такой запрос:
update user_activity a
set user_profile_id_int =
(select user_profile_id_int from user_profile b
where a.user_profile_id = b.user_profile_id);
Он работал на действительно сильном сервере в течение 1 дня, и я остановил его. Но для записи было обновлено.
Итак, 2 вопроса здесь:
- Есть ли лучший и более быстрый способ сделать это?
- Такой путь в порядке?
Решение
Ответ на вопрос 1
Это должно сделать это для вас
UPDATE user_activity a
INNER JOIN user_profile b
USING (user_profile_id)
SET a.user_profile_id_int = b.user_profile_id_int;
Это будет работать в MySQL. Если вы не привыкли к этому синтаксису соединения, сделайте это:
UPDATE user_activity a
INNER JOIN user_profile b
ON a.user_profile_id = b.user_profile_id
SET a.user_profile_id_int = b.user_profile_id_int;
Оба должны работать.
Ответ на вопрос 2
Ваш запрос, теоретически, работает. Однако посмотрите, что он делает:
Сканирование стола на user_activity
, индексированный поиск user_profile_id_int
Используя первичный ключ user_profile
, и на месте обновления текущего ряда в user_activity
.
Запрос попадает в два стола и два основных ключа, взад и вперед, на основе. Все шаги замедляют друг друга. Таким образом, вы получаете более длинный запрос.
ПРЕДОСТЕРЕЖЕНИЕ
Добавление составного индекса на user_profile
должен ускорить ситуацию:
ALTER TABLE user_profile ADD INDEX (user_profile_id,user_profile_id_int);
Другие советы
Я думаю, вы можете попробовать добавить LIMIT
к вашему обновлению (и немного измените WHERE
Чтобы отфильтровать уже измененные записи). Если вы это сделаете, например, LIMIT 100
, это не займет 1 день. Конечно, если вы хотите изменить все записи, вам придется написать сценарий, который выполняет UPDATE
до тех пор, пока количество обновленных строк не будет 0, но он не заблокирует всю таблицу.