如何针对单个查询进一步优化此MySQL表

Ron*_*per 5 mysql

我有一个InnoDB MySql Geo ID表,有大约100万行.表结构是这样的:

CREATE TABLE `geoid` (
   `start_ip` int(11) NOT NULL,
   `end_ip` int(11) NOT NULL,
   `city` varchar(64) NOT NULL,
   `region` char(2) NOT NULL,
   PRIMARY KEY (`start_ip`,`end_ip`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)

将只对该表运行一个类型查询:

SELECT city, region FROM geoid WHERE 1259650516 BETWEEN start_ip AND end_ip
Run Code Online (Sandbox Code Playgroud)

这个查询需要大约〜.4228秒,这不是超级慢但不是非常快的以太.

我的问题是:如何针对此单个查询进一步优化我的表?

我试过以下的事情:

  1. 将存储引擎更改为MyISAM,这使得查询大约需要1.9秒.
  2. 使用WHERE语句'WHERE geoid.start_ip <= 1259650516 AND 1259650516 <= geoid.end_ip'.但这需要大约0.5秒来执行而不是.4 ish.

我已从表中删除所有无用的行以使其变小.我需要所有100万行.

更新/解决方案

感谢下面的文章,这是我为解决这个问题所做的工作.(只是为了其他感兴趣的人完成这个答案)

我在上表中添加了一个新列:

ALTER TABLE `geoid` ADD `geoip` LINESTRING NOT NULL
Run Code Online (Sandbox Code Playgroud)

然后,我使用start_ip和end_ip中的地理数据填充新列

GeomFromText(CONCAT('LINESTRING(', start_ip, ' -1, ', end_ip, ' 1)'))
Run Code Online (Sandbox Code Playgroud)

然后,我在新列上创建了SPATIAL INDEX

CREATE SPATIAL INDEX geoip_index ON geoid(geoip);
Run Code Online (Sandbox Code Playgroud)

从那里,您所要做的就是将查询更改为:

SELECT city, region FROM geoid WHERE MBRContains(geoip, GeomFromText(CONCAT('POINT(', 1259650516, ' 0)')));
Run Code Online (Sandbox Code Playgroud)

和你完成.这使得查询从.42秒降低到.0003秒!!!!!!!

我喜欢这个INDEX.谢谢.希望能帮助到你.

Mar*_*ers 3

尝试在 上添加索引end_ip。在某些情况下,这应该会使查询速度提高两倍。

为了获得更好的性能,您需要使用 SPATIAL 索引,如本文所述。