【发布时间】:2014-11-06 06:52:56
【问题描述】:
我们有一张表用于在 MariaDB mariadb-5.5.37-1.el7_0.x86_64 上查找 IP 地理位置,如下所示:
创建表
ip2location_db24(idint(11) NOT NULL AUTO_INCREMENT,ip_fromint(10) unsigned DEFAULT NULL,ip_toint(10) unsigned DEFAULT NULL ,country_codechar(2) 整理 utf8_bin 默认为 NULL,country_namevarchar(64) 整理 utf8_bin 默认为 NULL,region_namevarchar(128) 整理 utf8_bin 默认为 NULL,
@ 987654328@ varchar(128) 整理 utf8_bin 默认空值,latitude双默认空值,longitude双倍默认空值,zip_codevarchar(30) 整理 utf8_bin 默认空值,
@ 987654332@ varchar(8) 整理 utf8_bin 默认空值,ispvarchar(255) 整理 utf8_bin 默认空值,domainvarchar(128) 整理 utf8_bin 默认空值,net_speedvarchar( ) 整理 utf8_bin 默认空值,idd_codevarchar(5) 整理 utf8_bin 默认空值,area_codevarchar(30) 整理 utf8_bin 默认空值,weather_station_codevarchar(10) 整理 utf8_bin 默认空值,weather_station_namevarchar(128) 整理 utf8_bin 默认为 NULL,
@98 7654340@ varchar(256) 整理 utf8_bin 默认空值,mncvarchar(256) 整理 utf8_bin 默认空值,mobile_brandvarchar(128) 整理 utf8_bin 默认空值,elevationint( ) 默认空值,usage_typevarchar(11) 整理 utf8_bin 默认空值,
主键 (id),
键idx_ip_from(ip_from),
键idx_latitude(latitude),
键idx_longitude(longitude),
键idx_ip_from_to_2(ip_to,ip_from)
) ENGINE=InnoDB AUTO_INCREMENT=9541211 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
ip_from 和 ip_to 列定义每个地理位置的开始和结束边界。
我们在这个表中有大约 1000 万条记录。
在查询给定 IP 的地理位置时,我们发现服务器遇到以下 SQL 的严重性能问题:
select * from ip2location_db24 where ip_to >=1908980838 and ip_from 编号:5475739
ip_from: 1908932608
ip_to: 1909063679
国家代码:CN
国家名称:中国
地区名称:山西
城市名称:太原
纬度:37.86944
经度:112.56028
邮编:-
时区:+08:00
isp:中国联通陕西省网络
域名:中国联通
网络速度:DSL
idd_code: 86
区号:0351
气象站代码:CHXX0129
气象站名称:太原
mcc: 460
跨国公司:01/06
mobile_brand: 中国联通
海拔:787
使用类型:ISP/MOB
一组中的 1 行(15.08 秒)
但是,使用以下等效 SQL 进行查询时,速度非常快。
select * from ip2location_db24 where ip_from 编号:5475739
ip_from: 1908932608
ip_to: 1909063679
国家代码:CN
国家名称:中国
地区名称:山西
城市名称:太原
纬度:37.86944
经度:112.56028
邮编:-
时区:+08:00
isp:中国联通陕西省网络
域名:中国联通
网络速度:DSL
idd_code: 86
区号:0351
气象站代码:CHXX0129
气象站名称:太原
mcc: 460
跨国公司:01/06
mobile_brand: 中国联通
海拔:787
使用类型:ISP/MOB
一组中的 1 行(0.00 秒)
问题是,当我们检查执行计划时,两个查询都对 ip_from 列的索引使用相同的范围扫描。但这两个 SQL 的性能还差得很远。有人知道这是什么原因吗?
为了提供更多信息,我们还测试了输出列完全被索引覆盖的查询。
MariaDB [ip2location] select ip_from,ip_to from ip2location_db24 where ip_to >=1908980838 and ip_from +------------+------------+
| ip_来自 | ip_to |
+------------+------------+
| 1908932608 | 1909063679 |
+------------+------------+
一组中的 1 行(0.01 秒)
请注意,上面的查询 SQL 快如闪电。但是在查询任何没有被索引覆盖的附加列时,它会花费令人难以置信的长时间:
> MariaDB [ip2location] select ip_from,ip_to,country_code from ip2location_db24 where ip_to >=1908980838 and ip_from +------------+------------+--------------+
| ip_来自 | ip_to |国家代码 |
+------------+------------+--------------+
| 1908932608 | 1909063679 |中国 |
+------------+------------+--------------+
一组中的 1 行(10.15 秒)
【问题讨论】:
标签: mysql sql query-optimization mariadb