我有一个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
答案 0 :(得分:2)
当前,您正在对每个查询进行全表扫描。您可以尝试几种方法。
使用EXPLAIN来确保数据库使用查询索引。
答案 1 :(得分:2)
优化器不知道您有一组不重叠的范围,它可以基于该范围进行一些优化。因此,您将更加努力地优化查询。
here中描述的代码将不执行表扫描,而将立即执行典型的查询。
直言不讳地说,您不对数据进行重组就无法优化查询。我也在和所有提供答案和评论的人交谈。
(对模式的评论)
ip
非常庞大。建议将city
及其后的所有字段移到另一个表中,以“标准化”该数据。
在同一张表中同时包含..code
和..name
(归一化表除外)是“错误的”。
几个字段可以(并且应该)是ascii,而不是utf8mb4。例如:countryCode。
关于另一个主题...您将如何处理AOL IP地址?据我了解,这些都是在其客户之间共享的。也就是说,“违反者”将四处走动,污染所有AOL IP。
10。,11.,172.16。,192.168。所有这些都来自NAT,并且不能与给定的国家或计算机关联。