Самый быстрый способ удалить дубликаты из другой таблицы, используя две строки - PullRequest
0 голосов
/ 29 октября 2011

Таблицы

CREATE TABLE `pending` (
  `auto_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  PRIMARY KEY (`auto_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=68176 ;

CREATE TABLE `errors` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `error` varchar(200) NOT NULL,
  `datechecked` date NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=11553 ;

Я использую следующий код, если я хочу просмотреть записи, в которых ожидаемое сочетание имени пользователя и пароля не соответствует ошибкам:

SELECT `pending`.username, `pending`.password FROM `pending` 
LEFT OUTER JOIN `errors` ON (
    `errors`.username = `pending`.username 
            AND 
    `errors`.password = `pending`.password
) WHERE (`errors`.username IS NULL)

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

||||||pending table|||||||||
----------------------------
username    | password 
----------------------------
brian       | password1
brian       | password2
brian       | password3
brian       | password4



||||||errors table|||||||||
----------------------------
username    | password 
----------------------------
brian       | password2
brian       | password4


Result:

----------------------------
username    | password 
----------------------------
brian       | password1
brian       | password3

Это работает, но для его завершения требуется много времени.Я выполняю это 20 раз в день или около того, и каждый запрос становится все длиннее и длиннее по мере роста таблицы ошибок.Я бы сказал, что у меня до 5 минут на оператор SQL, учитывая их размер записи по значению AUTO_INCREMENT.

У меня такое ощущение, что я могу создать какой-то индекс с использованием имени пользователя и пароля и повысить производительность.Хотя я не уверен на 100%, поэтому я спрашиваю об этом.

Ответы [ 2 ]

1 голос
/ 29 октября 2011

Попробуйте NOT EXISTS вместо LEFT JOIN.MySQL относительно медленно работает с объединениями.

SELECT p.username, p.password
FROM   pending p
WHERE  NOT EXISTS (SELECT * FROM errors WHERE (username, password) = (p.username, p.password))

Также убедитесь, что у вас есть индексы на ожидании (имя пользователя, пароль) и ошибки (имя пользователя, пароль).

CREATE INDEX username_password_idx ON pending (username, password);
CREATE INDEX username_password_idx ON errors (username, password);
0 голосов
/ 29 октября 2011

Прежде всего, убедитесь, что у вас есть составные индексы pending {username, password} и errors {username, password}.Я не слишком знаком с оптимизатором запросов MySQL, но большинство баз данных (и, надеюсь, MySQL также) должны иметь возможность использовать эти индексы для эффективного MERGE JOIN.

Кроме того, оптимизатор запросов MySQL может быть недостаточно умнымчтобы понять, что WHERE (errors.username IS NULL) на самом деле не требует полного сканирования таблицы (даже с индексами).Попробуйте что-то вроде этого:

SELECT `pending`.username, `pending`.password
FROM `pending` 
WHERE
    NOT EXISTS (
        SELECT *
        FROM `errors`
        WHERE 
            `errors`.username = `pending`.username 
            AND `errors`.password = `pending`.password
    )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...