Оптимизация запроса с большим объемом данных

sanich_
На сайте с 24.05.2008
Offline
77
735

Добрый день.

Прошу помощи у профессионалов по ускорению запроса для 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 поставил

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

explain select * from email_subscribe

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

Привожу 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

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

Лучший анализ бэков конкурентов - Yazzle (http://www.yazzle.ru/seo/8945eae37b4e842893f9c46afa70d80e/)
siv1987
На сайте с 02.04.2009
Offline
427
#1

SELECT t1.id FROM table t1 LEFT JOIN table t2 ON t1.ekey=t2.ekey WHERE t1.id>t2.id

+ индекс по полю ekey

edogs software
На сайте с 15.12.2005
Offline
775
#2
sanich_:
Добрый день.

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

id      ekey

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


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

Если нужно просто удалить дубликаты, то есть тупой и скоростной способ


ALTER IGNORE TABLE `tbl` ADD UNIQUE ( `ekey` )
ALTER TABLE `tbl` DROP INDEX `ekey`;

Если у Вас innoDB, то добавьте первой строкой


set session old_alter_table=1;
Разработка крупных и средних проектов. Можно с криптой. Разумные цены. Хорошее качество. Адекватный подход. Продаем lenovo legion в спб, дешевле магазинов, новые, запечатанные. Есть разные. skype: edogssoft
sanich_
На сайте с 24.05.2008
Offline
77
#3
edogs:
Если нужно просто удалить дубликаты, то есть тупой и скоростной способ

ALTER IGNORE TABLE `tbl` ADD UNIQUE ( `ekey` )
ALTER TABLE `tbl` DROP INDEX `ekey`;

Если у Вас innoDB, то добавьте первой строкой

set session old_alter_table=1;

Дело в том что мне не нужно удалять дубликаты, мне нужно их получить, чтобы в дальнейшем обработать...

---------- Добавлено 29.10.2015 в 15:40 ----------

siv1987:
SELECT t1.id FROM table t1 LEFT JOIN table t2 ON t1.ekey=t2.ekey WHERE t1.id>t2.id

+ индекс по полю ekey

Исходные значения в таблице:

id      ekey 

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

Не пойму как работает запрос, он возвращает мне неправильное множество:

id

2
4
5
4
5
5

А должен вернуть повторяющие по полю ekey записи:

id      ekey 

2 ключ1
4 ключ1
5 ключ1
siv1987
На сайте с 02.04.2009
Offline
427
#4

GROUP BY t1.id

Хелпзонович
На сайте с 15.06.2005
Offline
133
#5


select id,ekey, count(id) as c from email_subscribe group by ekey having c>1
Вы там держитесь! Хорошего вам настроения. Здоровья.
alexvaleev
На сайте с 04.02.2010
Offline
55
#6

select distinct a.id, a.ekey from email_subscribe a inner join email_subscribe b on a.ekey=b.ekey where a.id>b.id

А вообще так делать нельзя, хоть в mysql и работает:

SELECT id FROM email_subscribe GROUP BY ekey
Блог (http://alexvaleev.ru) Всем роуп! (https://rujump.ru/)
A
На сайте с 19.07.2010
Offline
130
#7
Хелпзонович:

select id,ekey, count(id) as c from email_subscribe group by ekey having c>1

Это правильный ответ. Запрос выдаст только дупы, их можно смело удалять. После удаления запрос нужно запустить еще раз для удаления следующей партии дупов. И так несколько раз.

Нужен еще индекс по полю ekey. Работает быстро, гонял похожие запросы на табличках по несколько лямов записей.

ps: join-ы и т.д. для таких целей совсем не нужны.

А вообще так делать нельзя, хоть в mysql и работает:
SELECT id FROM email_subscribe GROUP BY ekey

В классическом SQL нужно к полю id добавить одну из функций: min(), max(), first(), last().

MySQL не заморачивается с этим и вариант с id работает. :)

Запрос выдаст id всех уникальных записей (которые нельзя удалять). Все остальные id, которые не выдал запрос - дупы.

.............

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий