Медленный запрос на самостоятельное удаление - PullRequest
1 голос
/ 17 августа 2011

Это проще, чем этот запрос?

delete a.* from matches a
    inner join matches b ON (a.uid = b.matcheduid)

Да, по-видимому, так и есть ... потому что производительность по вышеуказанному запросу очень низкая, когда таблица matches очень большая.

matches - это около 220 миллионов записей. Я надеюсь, что этот запрос DELETE уменьшит размер примерно до 15 000 записей. Как я могу улучшить производительность запроса? У меня есть индексы на обоих столбцах. UID и MatchedUID являются единственными двумя столбцами в этой таблице InnoDB, оба имеют тип INT (10) без знака. Запрос выполняется на моем ноутбуке более 14 часов (процессор i7).

Ответы [ 3 ]

7 голосов
/ 17 августа 2011

Удаление такого большого количества записей может занять некоторое время, я думаю, что это происходит настолько быстро, насколько это возможно, если вы делаете это таким образом.Если вы не хотите инвестировать в более быстрое оборудование, я предлагаю другой подход:

Если вы действительно хотите удалить 220 миллионов записей, чтобы в таблице оставалось только 15 000 записей, то есть около 99 999% от всехзаписей.Почему бы не

  1. Создать новую таблицу,
  2. , просто вставить все записи, которые вы хотите выжить,
  3. и заменить старую на новую?

Примерно так может работать немного быстрее:

/* creating the new table */
CREATE TABLE matches_new
SELECT a.* FROM matches a
LEFT JOIN matches b ON (a.uid = b.matcheduid)
WHERE ISNULL (b.matcheduid)

/* renaming tables */
RENAME TABLE matches TO matches_old;
RENAME TABLE matches_new TO matches;

После этого вам просто нужно проверить и создать нужные вам индексы, которые должны быть достаточно быстрыми, если работать только с 15.000 записями..

0 голосов
/ 17 августа 2011

Возможно, я настраиваю себя здесь на обжарку, но при выполнении операции удаления, подобной этой, в процессе самосоединения, не является ли запрос повторным вычислением индекса соединения после каждого удаления?

Хотя это неуклюжая и грубая сила, вы можете подумать:

A.Создайте временную таблицу для хранения идентификатора пользователя, полученного в результате внутреннего соединения, затем присоединитесь к ТО, ТО, затем выполните удаление.

ИЛИ

B.Добавьте столбец логического (битового) типа, используйте объединение, чтобы пометить каждое совпадение (эта операция должна быть БЫСТРАЯ), а затем используйте:

DELETE * FROM matches WHERE YourBitFlagColumn = True

Затем удалите логический столбец.

0 голосов
/ 17 августа 2011

выполнение объяснения выберите a. * Из совпадений совпадений внутреннего соединения b ON (a.uid = b. Matcheduid) объяснит, как ваши индексы присутствуют и используются

...