Улучшить производительность запроса на удаление - PullRequest
0 голосов
/ 17 ноября 2018

Я хочу удалить записи из таблицы B, поэтому для A_id (только с наибольшим идентификатором) существует только одна запись

Таблица A :

+----+------------+
| id |    name    |
+----+------------+
|  1 | Some name  |
|  2 | Other name |
+----+------------+

Таблица B :

+----+-------+------+
| id | stuff | A_id |
+----+-------+------+
|  1 | aab   |    1 |
|  2 | aac   |    1 |
|  3 | aad   |    2 |
|  4 | aae   |    1 |
|  5 | aak   |    1 |
|  6 | aal   |    2 |
+----+-------+------+

Мой текущий запрос (работает нормально):

DELETE FROM B 
WHERE id NOT IN (SELECT MAX(id)
                 FROM B
                 GROUP BY A_id)

Что приводит к правильному результату:

+----+-------+------+
| id | stuff | A_id |
+----+-------+------+
|  5 | aak   |    1 |
|  6 | aal   |    2 |
+----+-------+------+

Но это очень и очень медленно, когда в таблице B много строк. Есть ли способ повысить производительность запроса (или, возможно, сделать это совершенно по-другому?)

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

Вы удаляете большое количество строк. Это проблема. В удалениях много накладных расходов.

Если вы удаляете значительное количество строк в таблице - и значимое может составлять всего несколько процентов - тогда часто быстрее воссоздать таблицу:

select b.*
into temp_b  -- actually, I wouldn't use a temporary table in case the server goes down
from b
where b.id = (select max(a.id) from b b2 where b2.id = b.a_id);

truncate table b;

insert into b
    select *
    from temp_b;

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

Обратите внимание, что я изменил структуру NOT IN. Я настоятельно не рекомендую использовать NOT IN, потому что семантика не интуитивна, когда подзапрос возвращает значения NULL. Если бы существовало только одно значение NULL, то WHERE никогда не получило бы значение ИСТИНА. Даже если значения NULL не являются проблемой в этом случае, я настоятельно рекомендую использовать другие альтернативы, чтобы у вас не возникало проблем, когда возможны NULL s.

Для производительности на SELECT требуется индекс на b(a_id, id). Вы можете обнаружить, что такой индекс помогает в исходном запросе.

0 голосов
/ 17 ноября 2018

Ваш запрос выглядит нормально для меня.

Похоже, ваша проблема в том, что у вас очень большой объем данных и вам нужны способы оптимизации производительности.

Что вы можете сделать, это материализовать свойподзапрос и убедитесь, что max_id проиндексирован, например, сделав его первичным ключом.

Итак, создайте временную таблицу Max_B и сохраните результаты своего подзапроса в этой таблице.Затем выполните удаление и впоследствии удалите временную таблицу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...