使用INNER连接的SQL查询花费的时间太长

时间:2019-06-29 18:08:57

标签: mysql sql

我有一个数据库,在其中保存了已删除的代理,然后不断对其进行检查,问题是我有一个函数,该函数使用指定的过滤器来计算代理总数,例如:来自美国的HTTP代理,至少有70%的正常运行时间大约需要4到5秒钟,这不是很多时间,但是用户迫不及待地想要更新计数器。

要过滤所有代理,在这种情况下,我使用2个表 表格称为代理,在这里我插入具有一般信息,ISP,国家/地区,协议等的代理

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代理,并且保存正常运行时间,检查失败,平均ping等(这两个表中的代理都是重复的,我的意思是,如果代理是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)和仅通过代理(检测到代理)

我还想补充一点,每次用户从表单中修改任何值时,计数器都会使用JS更新(表示系统执行查询)

2 个答案:

答案 0 :(得分:0)

查询中优化的关键方面是过滤条件。选择性最高的似乎是:第一个proxies.country和第二个proxies.ishttp

因此,我将创建以下索引:

create index ix1 on proxies (country, ishttp);

create index ix2 on http (ip, uptime);

答案 1 :(得分:0)

这是您的查询:

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上的条件产生的行少于代理条件上的行,则使用第二组索引。如果相反,则使用第一个。