使用INET_ATON时的MySQL性能问题

时间:2018-10-19 11:45:38

标签: mysql performance

我有一个MySQL查询

SELECT * FROM table WHERE INET_ATON("10.0.0.1") BETWEEN INET_ATON(s_ip) AND INET_ATON(e_ip);

当用户访问网站时,“ 10.0.0.1”会动态出现,并且s_ip是起始ip地址列,该列可能以“ 10.0.0.0”作为起始ip地址范围,而e_ip是终止IP地址。

现在,问题是我有将近35万条记录,当执行该查询时,它们只做一件事,这就是让我获得访问者的国家/地区代码。

执行此查询时,MySQL的CPU消耗峰值达到1100%,并将其乘以1000个请求/分钟,而我的服务器无法处理它。

我的服务器运行的CentOS 7带有100 GB的RAM和24个核心,时钟频率为3.0 GHz,但是性能仍然成为我的噩梦。

我当时正在考虑将此功能外包给第三方服务,但是我只是想确保自己没有办法解决此问题。

(来自评论)

CREATE TABLE ip` (
    ip_ip varbinary(16) NOT NULL, 
    ip_last_request_time timestamp(3) NULL DEFAULT NULL, 
    ip_min_timeSpan_get smallint(5) unsigned NOT NULL, 
    ip_min_timeSpan_post smallint(5) unsigned NOT NULL, 
    ip_violationsCount_get smallint(5) unsigned NOT NULL, 
    ip_violationsCount_post smallint(5) unsigned NOT NULL, 
    ip_maxViolations_get smallint(5) unsigned NOT NULL, 
    ip_maxViolations_post smallint(5) unsigned NOT NULL, 
    ip_bannedAt timestamp(3) NULL DEFAULT NULL,
    ip_banSeconds mediumint(8) unsigned NOT NULL DEFAULT '300', 
    ip_isCapatchaResolved tinyint(1) NOT NULL DEFAULT '0', 
    ip_isManualBanned tinyint(1) NOT NULL DEFAULT '0', 
    ip_city varchar(45) DEFAULT '', 
    ip_region varchar(45) DEFAULT '', 
    ip_regionCode varchar(5) DEFAULT '', 
    ip_regionName varchar(45) DEFAULT '', 
    ip_countryCode varchar(3) DEFAULT '', 
    ip_countryName varchar(45) DEFAULT '', 
    ip_continentCode varchar(3) DEFAULT '', 
    ip_continentName varchar(45) DEFAULT '', 
    ip_timezone varchar(45) DEFAULT '', 
    ip_currencyCode varchar(4) DEFAULT '', 
    ip_currencySymbol_UTF8 varchar(5) DEFAULT '', 
    PRIMARY KEY (ip_ip), 
    KEY countryCode_index (ip_countryCode)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`

CREATE TABLE country` ( co_id char(2) COLLATE utf8mb4_unicode_ci NOT NULL, 
    co_re_id smallint(6) DEFAULT NULL, 
    co_flag_id char(4) COLLATE utf8mb4_unicode_ci NOT NULL, 
    co_english_name varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL, 
    PRIMARY KEY (co_id), 
    KEY fk_country_region1_idx (co_re_id), 
    CONSTRAINT fk_country_region1 FOREIGN KEY (co_re_id)
              REFERENCES region (re_id) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

2 个答案:

答案 0 :(得分:2)

当前,您正在对每个查询进行全表扫描。您可以尝试几种方法。

  • 将INET_ATON(s_ip)存储在表中,以便在查询过程中不进行计算。 e_ip也一样。
  • 添加一个包含这两个新列以及国家/地区代码的索引。
  • 更改查询以选择国家/地区代码,然后使用两个新列。

使用EXPLAIN来确保数据库使用查询索引。

答案 1 :(得分:2)

优化器不知道您有一组不重叠的范围,它可以基于该范围进行一些优化。因此,您将更加努力地优化查询。

here中描述的代码将不执行表扫描,而将立即执行典型的查询。

直言不讳地说,您不对数据进行重组就无法优化查询。我也在和所有提供答案和评论的人交谈。

(对模式的评论)

ip非常庞大。建议将city及其后的所有字段移到另一个表中,以“标准化”该数据。

在同一张表中同时包含..code..name(归一化表除外)是“错误的”。

几个字段可以(并且应该)是ascii,而不是utf8mb4。例如:countryCode。

关于另一个主题...您将如何处理AOL IP地址?据我了解,这些都是在其客户之间共享的。也就是说,“违反者”将四处走动,污染所有AOL IP。

10。,11.,172.16。,192.168。所有这些都来自NAT,并且不能与给定的国家或计算机关联。