оптимизация mysql UPDATE JOIN индексы производительности

0

У меня есть этот запрос:

"explain UPDATE requests R JOIN profile as P ON R.intern_id = P.intern_id OR R.intern_id_decoded = P.intern_id OR R.intern_id_full_decode = P.intern_id SET R.found_id=P.id WHERE R.id >= 28000001 AND R.id <= 28000001+2000000 AND R.found_id is NULL"
1       UPDATE  R       NULL    range   PRIMARY,intern_id_customer_id_batch_num,id_found_id     PRIMARY 4       NULL    3616888 10.00   Using where
1       SIMPLE  P       NULL    ALL     intern_id_dt_snapshot,intern_id NULL    NULL    NULL    179586254       27.10   Range checked for each record (index map: 0x6)

Этот запрос занимает около 40 секунд для выполнения, он обновляет 5000-10000 строк из набора из 2 миллионов строк.

В настоящее время я обновляю 2 миллиона строк "jobs", чтобы сделать соединение более быстрым. Вся таблица составляет 170 миллионов записей в настоящее время.

EXPLAIN показывает вторую часть без использования INDEX, я не уверен, правильно это или нет. Поля intern_id - это varchars, found_id и id - INT

Кажется ли, что результат работы объясняется работой? Я заметил, что вторая строка не использует индекс, не уверен, что это нормально.

  • 0
    Кажется, я вспоминаю, как MySQL прекращал использовать индексы, когда вы выполняете диапазон. Попробуйте сначала поместить R.found_id IS NULL.
  • 0
    Без изменений в выводе, к сожалению
Теги:
mariadb

2 ответа

1
Лучший ответ

Я бы сделал эту логику, используя несколько соединений:

UPDATE requests r LEFT JOIN
       profile p1
       ON r.intern_id = p1.intern_id LEFT JOIN
       profile p2
       ON r.intern_id_decoded = p2.intern_id AND p1.id IS NULL LEFT JOIN
       profile p3
       ON r.intern_id_full_decode = p3.intern_id AND p2.id IS NULL
    SET r.found_id = COALESCE(p1.id, p2.id, p3.id)
    WHERE R.id >= 28000001 AND R.id <= 28000001 + 2000000 AND
          R.found_id is NULL;

Базы данных очень плохие при оптимизации OR в условиях JOIN. Это может быть лучше с явным JOIN s.

Условия ON также обеспечивают только первое совпадение.

  • 0
    Я играю с этим прямо сейчас, и это значительно быстрее. Вероятно, в 10-15 раз лучше, чем раньше. Спасибо
1

Я бы сделал 3 перезагруженных UPDATEs - по одному для каждого из условий ON.

Строки 10K для обновления чрезмерны; сверните его до 1K. Это означает прокрутку блока до 200K. (Скорость может быть даже быстрее).

UPDATE ... ON P.intern_id = R.intern_id          SET ... WHERE ...
UPDATE ... ON P.intern_id = R.intern_id_decoded  SET ... WHERE ...
UPDATE ... ON P.intern_id = R.intern_id_full     SET ... WHERE ...

(Диапазон является одним и тем же перед каждым набором из 3, тем самым помогая с кешированием R.)

Возможно, INDEX(found_id) поможет, но это не так.

См. Здесь дополнительные предложения, особенно советы по поиску 1000 строк перед началом операции:

SELECT id WHERE id > ... AND found_id IS NULL LIMIT 1000,1;

Затем используйте это как предел вместо 2-миллионной. Цель здесь состоит в том, чтобы выровнять количество обновленных строк.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню