Оптимизируйте сравнение данных в двух больших MySQL таблицах - PullRequest
0 голосов
/ 09 января 2020

Как я могу оптимизировать запрос, который найдет все записи, которые:

  • имеют Activation_request.date_confirmed не нуль

и

  • не имеет связанного строкового значения в другой таблице: activ_request.email = user.username не должно возвращать никаких записей

Я пытался:

SELECT  email 
FROM activation_request l 
    LEFT JOIN user r ON r.username = l.email 
WHERE l.date_confirmed is not null 
AND r.username IS NULL

и

SELECT email 
FROM  activation_request 
WHERE  date_confirmed is not null 
AND NOT EXISTS (SELECT 1 
                FROM user  
                WHERE  user.username = activation_request.email
                )

но в обеих таблицах есть записи xxx.xxx.xxx, поэтому после всех ночей выполнения этих запросов, к сожалению, я не получил никаких результатов.

Создать операторы:

CREATE TABLE `activation_request` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `version` bigint(20) NOT NULL,
  `date_confirmed` datetime DEFAULT NULL,
  `email` varchar(255) NOT NULL,
  (...)
  PRIMARY KEY (`id`),
  KEY `emailIdx` (`email`),
  KEY `reminderSentIdx` (`date_reminder_sent`),
  KEY `idx_resent_needed` (`date_reminder_sent`,`date_confirmed`),
) ENGINE=InnoDB AUTO_INCREMENT=103011867 DEFAULT CHARSET=utf8;




CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `version` bigint(20) NOT NULL,
  `username` varchar(255) NOT NULL,
  (...)
  PRIMARY KEY (`id`),
  UNIQUE KEY `Q52plW9W7TJWZcLj00K3FmuhwMSw4F7vmxJGyjxz5iiINVR9fXyacEoq4rHppb` (`username`),
) ENGINE=InnoDB AUTO_INCREMENT=431400048 DEFAULT CHARSET=latin1;

Объяснить для LEFT JOIN:

[[id: 1, select_type: SIMPLE, таблица: l, тип: ALL, возможные_ключи: null, ключ: null, key_len: null, ref: null, строки: 49148965 , Дополнительно: Использование where], [id: 1, select_type: SIMPLE, таблица: r, тип: index, возможные_ключи: null, ключ: Q52plW9W7TJWZcLj00K3FmuhwMSw4F7vmxJGyjxz5iiINVR9fXyacEoq4rHppll; 256: ref: 23, row: 26: 26, код: 26, строка 26, код: 26: 23, строка 26: refN: 26, строка: 26: 26, код: 26, код: 26: 26, код: 26, код: 26: 26, код: 26, код: 26: 26, код: 26: 26; Не существует; Использование индекса; Использование буфера соединения (блочный вложенный L oop)]] [[id: 1, select_type: SIMPLE, таблица: l, тип: ALL, возможные_ключи: null, ключ: null, key_len: null, ref: null, строки: 49148965 , Дополнительно: Использование where], [id: 1, select_type: SIMPLE, таблица: r, тип: index, возможные_ключи: null, ключ: Q52plW9W7TJWZcLj00K3FmuhwMSw4F7vmxJGyjxz5iiINVR9fXyacEoq4rHppll; 256: ref: 23, row: 26: 26, код: 26, строка 26, код: 26: 23, строка 26: refN: 26, строка: 26: 26, код: 26, код: 26: 26, код: 26, код: 26: 26, код: 26, код: 26: 26, код: 26: 26; Не существует; Использование индекса; Использование буфера соединения (блочный вложенный L oop)]]

После добавления индексов для промежуточной базы данных (с немного меньшим количеством данных, но той же структурой) запрос теперь выполняется ~ 24 часа и до сих пор не дал результатов) :

$ show processlist;

| Id | User    | Host                                            | db       | Command | Time   | State        | Info 
| 64 | root    | localhost                                       | staging_db   | Query   | 110072 | Sending data | SELECT ar.email FROM  activation_request ar WHERE ar.date_confirmed is not null AND NOT EXISTS (SELE |

Mysql версия:

$ select version();
5.6.16-1~exp1

Все остальные команды в списке Sleep, поэтому не выполняется ни один другой запрос и, возможно, нарушающие / блокирующие строки.

1 Ответ

0 голосов
/ 10 января 2020

Для этого запроса:

SELECT ar.email 
FROM  activation_request ar
WHERE ar.date_confirmed is not null AND
      NOT EXISTS (SELECT 1 
                  FROM user u
                  WHERE u.username = ar.email
                 )

Я бы порекомендовал индексы на activation_request(date_confirmed, email) и user(username).

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

...