MySQL在使用INET_ATON时的性能问题

MySQL在使用INET_ATON时的性能问题,mysql,performance,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地址 现在,问题是我有大约350K条记录,当执行这个查询时,这些记录只做一件事,那就是给我访客的国家代码 当执行此查询时,MySQL的CPU消耗

我有一个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地址

现在,问题是我有大约350K条记录,当执行这个查询时,这些记录只做一件事,那就是给我访客的国家代码

当执行此查询时,MySQL的CPU消耗峰值为1100%,再乘以1000个请求/分钟,我的服务器就无法处理它

我的服务器运行的是CentOS 7,有100 GB的RAM和24个时钟频率为3.0 GHz的内核,但性能对我来说仍然是一场噩梦

我曾考虑将此功能外包给第三方服务,但我只想确保我方无法解决此问题

(来自评论)


目前,您正在对每个查询执行完整的表扫描。有几件事你可以试试

  • 将INET_ATON(s_ip)存储在表中,以便在查询期间不计算它。e_ip也一样
  • 添加一个包含这两个新列和国家/地区代码的索引
  • 将查询更改为仅选择国家代码,并使用两个新列

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

当前,您正在对每个查询执行完整的表扫描。有几件事你可以试试

  • 将INET_ATON(s_ip)存储在表中,以便在查询期间不计算它。e_ip也一样
  • 添加一个包含这两个新列和国家/地区代码的索引
  • 将查询更改为仅选择国家代码,并使用两个新列

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

优化器不知道您有一组非重叠范围,它可以在此基础上进行一些优化。因此,您必须更加努力地优化查询

所描述的代码将“立即”执行典型的查询,而不是执行表扫描


坦率地说,如果不重新构造数据,就无法优化查询。我也在向所有提供答案和评论的人讲话

(图式批判)

ip
太笨重了。建议将
city
及其后的所有字段移动到另一个表中,以便“规范化”该数据

.code
.name
都放在同一个表中是“错误的”(规范化表除外)

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

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


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

优化器不知道您有一组非重叠范围,它可以在此基础上进行一些优化。因此,您必须更加努力地优化查询

所描述的代码将“立即”执行典型的查询,而不是执行表扫描


坦率地说,如果不重新构造数据,就无法优化查询。我也在向所有提供答案和评论的人讲话

(图式批判)

ip
太笨重了。建议将
city
及其后的所有字段移动到另一个表中,以便“规范化”该数据

.code
.name
都放在同一个表中是“错误的”(规范化表除外)

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

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


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

显示表格结构、一些示例数据并解释输出。我有表IP,其中有(IP PK,countryCode,…)和表country,其中有(countryCode PK,countryName,countryFlagCode,countryCurrency,…)使用此模式和IP列上的PK索引,您可以在没有性能问题的情况下缩放和查询IP,只要确保优化器在您根据IPIf进行选择时使用IP上的索引,您从包含195条记录的countries表中进行选择,您不应该有性能问题(但是,您应该按照Joni Answer的建议进行优化)但是,如果您是从IPs表中选择的,那么IPs表中的
s_ip
e_ip
是什么意思,正如Raymond Nijland所说,请显示表结构、一些数据并解释您想做什么do@Accountantم-请提供
SHOW CREATE TABLE
;简短的des中可能缺少一些微妙的问题scription.
10.x.y.z
是“私有”空间——任何国家的任何人都可以拥有所有这些IP地址。例如,请参见显示表结构、一些示例数据和解释输出。我有表IP,其中有(IP PK,countryCode,…)和表country,其中有(countryCode PK,countryName,countryFlagCode,countryCurrency,…)使用此模式和IP列上的PK索引,您可以在没有性能问题的情况下缩放和查询IP,只要确保优化器在您根据IPIf进行选择时使用IP上的索引,您从包含195条记录的countries表中进行选择,您不应该有性能问题(但是,您应该按照Joni Answer的建议进行优化)。但是,如果您从IPs表中选择,那么IPs表中的
s_ip
e_ip
意味着什么,正如Raymond Nijland所说,请显示表结构,一些数据
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