Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MySQL > Оптимизация запроса с большим объемом данных


Автор: sanich_ 27.10.2015, 20:27
Добрый день.

Прошу помощи у профессионалов по ускорению запроса для Mysql
Есть таблица email_subscribe с набором значений:

Код

id      ekey
1       ключ1
2       ключ1
3       ключ2
4       ключ1
5       ключ1


Необходимо получить дубликаты по полю "ekey", которые в дальнейшем можно удалить 

Сделал 2 запроса, они выводят, список нужных дублей по полю "ekey", которые можно потом удалить...

Код

SELECT t.* FROM email_subscribe t  
LEFT JOIN (SELECT id FROM email_subscribe GROUP BY ekey) as t2 ON t.id=t2.id  
WHERE t2.id IS NULL


Код

select * from email_subscribe 
where id not in (SELECT id FROM email_subscribe GROUP BY ekey)


Результат двух запросов правильный и идентичный:
Код

id      ekey
2       ключ1
4       ключ1
5       ключ1



Проблема в том, что при больших объемах данных (если в таблице email_subscribe будет 700 000 записей) эти запросы очень долго выполняются, не могу дождаться завершения запроса на локальном хосте при ~160 000 строк

Индексы по нужным полям таблицы email_subscribe поставил
Результат
http://sss.ssmaker.ru/6890cbdb.png

Привожу explain запроса:
Код

explain select * from email_subscribe
where id not in (SELECT id FROM email_subscribe GROUP BY ekey)

Результат
http://sss.ssmaker.ru/b9ae2dfc.png

Привожу explain запроса:
Код

explain SELECT t.* FROM email_subscribe t
LEFT JOIN (SELECT id FROM email_subscribe GROUP BY ekey) as t2 ON t.id=t2.id  
WHERE t2.id IS NULL

Результат
http://ssmaker.ru/917b73a2.png

В чем причина длительного выполнения обоих запросов?

Автор: Akina 27.10.2015, 20:58
Explain принято давать цитатой с консоли в теге кода. Если не умеете - то скриншотом, присоединённым к сообщению. Но уж никак не ссылкой в хрен знает куда...
Ну и при http://www.sql.ru/forum/1182033/optimizaciya-zaprosa-s-bolshim-obemom-dannyh принято давать ссылку.

Автор: Angel_666 28.10.2015, 11:05
Код

SELECT t.* FROM email_subscribe t  
LEFT JOIN (SELECT id FROM email_subscribe GROUP BY ekey) as t2 ON t.id=t2.id  
WHERE t2.id IS NULL


t.* тебе так нужны все поля данной таблицы? ограничь необходимым полем id и ekey

Код

SELECT count(*) AS count,
id,
ekey
FROM email_subscribe
GROUP BY id, ekey
ORDER BY email_subscribe.ekey DESC


Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Optimizatsiya-zaprosa-s-bolshim-obyemom-dannykh-id562fb49bae2015657e8b4567#findElement_E7045_563081afae20157965887081_0

Автор: tzirechnoy 28.10.2015, 14:51
Код
CREATE TEMPORARY TABLE expval AS 
        SELECT min(id) AS id, ekey 
    FROM email_subscribe
    GROUP BY ekey;
START TRANSACTION;
  DELETE * FROM email_subscribe;
  INSERT INTO email_subscibe (id, ekey) SELECT id, ekey FROM expval;
COMMIT;



Есть ещё вариант потом удалить только те записи, которые не попали в эту временную таблицу, но это сложнее и требует индэксов на expval для нормальной работы.
   

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)