MySQL Select работает нормально, но Delete зависает бесконечно в зависимости от положения GROUP BY - PullRequest
0 голосов
/ 09 мая 2019
select * from table1 where ID in (
    select min(a.ID) from (select * from table1) a group by id_x, id_y, col_z having count(*) > 1)

Вышеупомянутый запрос выполнялся за 2,2 секунды, возвращая четыре результата.Теперь, когда я изменяю select * на delete, он зависает бесконечно.

delete from table1 where ID in (
    select min(a.ID) from (select * from table1) a group by id_x, id_y, col_z having count(*) > 1)

Если я переместу позицию предложения group by в запросе выбора псевдонима, он больше не будет зависать.

delete from table1 where ID in (
    select a.ID from (select min(ID) from table1 group by id_x, id_y, col_z having count(*) > 1) a)

Почему он зависает? Несмотря на то, что (select * from table1) извлекает миллионы записей, кажется, что запрос не прекращается в течение нескольких часов.Кто-нибудь может объяснить, что мешает запросу?Меня это озадачивает, потому что запрос на выборку работает нормально, тогда как запрос на удаление зависает.

РЕДАКТИРОВАТЬ: Мой фокус здесь - почему он зависает.Я уже разместил обходной путь, который отлично работает.Но для того, чтобы разработать систему профилактики, мне нужно выяснить причину этого ..

Ответы [ 2 ]

0 голосов
/ 09 мая 2019

Попробуйте:

delete t
    from table1 t join
         (select min(id) as min_id
          from table1
          group byid_x, id_y, col_z
          having count(*) >= 2
         ) tt
         on tt.min_id = t.id;

Тем не менее, вы, вероятно, не хотите удалять только минимальный идентификатор.Я предполагаю, что вы хотите сохранить самый последний идентификатор.Если так:

delete t
    from table1 t left join
         (select max(id) as max_id
          from table1
          group byid_x, id_y, col_z
          having count(*) >= 2
         ) tt
         on tt.max_id = t.id
    where tt.max_id is null;
0 голосов
/ 09 мая 2019

Используйте JOIN вместо WHERE ID IN (SELECT ...).

DELETE t1
FROM table1 AS t1
JOIN (
    SELECT MIN(id) AS minId
    FROM table1
    GROUP BY id_x, id_y, col_z 
    HAVING COUNT(*) > 1) AS t2
ON t1.id = t2.minId

Я думаю, что ваш запрос не оптимизируется, потому что он должен пересчитывать подзапрос после каждого удаления, так как удаление строки может изменить MIN(id) для этой группы. Использование JOIN требует, чтобы группировка и агрегирование выполнялись только один раз.

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