SQL-запрос с INNER join занимает слишком много времени - PullRequest
0 голосов
/ 29 июня 2019

У меня есть БД, где я сохраняю прокси-серверы, а затем постоянно проверяю их, проблема в том, что у меня есть функция, которая подсчитывает общее количество прокси с использованием указанного фильтра, например: HTTP-прокси из США с не менее 70% времени безотказной работы и это занимает от 4 до 5 секунд, это не много времени, но пользователь не может ждать в этот раз, чтобы обновить счетчик.

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

CREATE TABLE `proxies` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `ip` varchar(255) NOT NULL,
 `port` varchar(255) NOT NULL,
 `ishttp` varchar(255) NOT NULL,
 `ishttps` varchar(255) NOT NULL,
 `issocks4` varchar(255) NOT NULL,
 `issocks5` varchar(255) NOT NULL,
 `country` varchar(255) NOT NULL,
 `city` varchar(255) NOT NULL,
 `isp` varchar(255) NOT NULL,
 `ismobile` varchar(10) NOT NULL,
 `isdetected` varchar(10) NOT NULL,
 `date_added` varchar(255) NOT NULL,
 `last_checked` varchar(255) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7981 DEFAULT CHARSET=latin1

и таблицу с именем http, здесь я вставляю ТОЛЬКО прокси-серверы http и сохраняю время безотказной работы, неудачные проверки, средний пинг и т. Д. (Прокси дублируются в обеих таблицах, я имею в виду, если прокси-сервер HTTP переходит к прокси-серверам и HTTP)

CREATE TABLE `http` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `ip` varchar(20) NOT NULL,
 `port` varchar(10) NOT NULL,
 `total` int(11) NOT NULL,
 `successful` int(11) NOT NULL,
 `failed` int(11) NOT NULL,
 `last_successful` varchar(255) NOT NULL,
 `last_failed` varchar(255) NOT NULL,
 `uptime` varchar(255) NOT NULL,
 `last_response` varchar(255) NOT NULL,
 `response_sum` varchar(255) NOT NULL,
 `avg_response` varchar(255) NOT NULL,
 `anonimity` varchar(20) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3776 DEFAULT CHARSET=latin1

На самом деле, для фильтрации прокси, которые я использую INNER JOIN, вот пример:

SELECT * FROM http INNER JOIN proxies ON http.ip=proxies.ip WHERE ishttp='yes' AND country='USA' AND uptime >= '50'

Это всего лишь пример, пользователь может фильтровать по анонимности (http.anonimity), стране (proxies.country), времени работы (http.uptime), ping (http.avg_response), только мобильным прокси (proxies.ismobile) и только пропущенные прокси (proxies.isdetected)

Я также хочу добавить, что счетчик обновляется (это означает, что система выполняет запрос), используя JS, и каждый раз, когда пользователь изменяет любое значение из формы

Ответы [ 2 ]

0 голосов
/ 29 июня 2019

Это ваш запрос:

SELECT *
FROM http h INNER JOIN
     proxies p
     ON h.ip = p.ip
WHERE p.ishttp = 'yes' AND p.country = 'USA' AND
      h.uptime >= '50';

Для этого запроса есть два подхода к индексам, в зависимости от того, насколько избирательны условия. Один из них:

  • proxies(country, ishttp, ip)
  • http(ip, uptime)

Другой:

  • http(uptime, ip)
  • proxies(ip, country, ishttp)

Что лучше зависит от селективности: если условие на uptime создает меньше строк, чем условие на прокси, то используйте второй набор индексов. Если наоборот, используйте первый.

0 голосов
/ 29 июня 2019

Ключевым аспектом оптимизации вашего запроса являются критерии фильтрации. Наиболее избирательным кажется: первый proxies.country, а второй proxies.ishttp.

Поэтому я бы создал следующие индексы:

create index ix1 on proxies (country, ishttp);

create index ix2 on http (ip, uptime);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...