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

时间:2011-09-25 20:17:20

标签: 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;

此表只会运行一种类型的查询:

SELECT city, region FROM geoid WHERE 1259650516 BETWEEN start_ip AND end_ip

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

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

我尝试了以下事项:

  1. 将存储引擎更改为MyISAM,这使得查询大约需要1.9秒。
  2. 使用WHERE语句' WHERE geoid.start_ip< = 1259650516 AND 1259650516< = geoid.end_ip'。但这需要大约0.5秒来执行而不是.4 ish。
  3. 我已从表中删除所有无用的行以使其变小。我需要所有100万行。

    更新/解决方案

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

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

    ALTER TABLE `geoid` ADD `geoip` LINESTRING NOT NULL
    

    然后我用start_ip和end_ip

    中的地理数据填充了新列
    GeomFromText(CONCAT('LINESTRING(', start_ip, ' -1, ', end_ip, ' 1)'))
    

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

    CREATE SPATIAL INDEX geoip_index ON geoid(geoip);
    

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

    SELECT city, region FROM geoid WHERE MBRContains(geoip, GeomFromText(CONCAT('POINT(', 1259650516, ' 0)')));
    

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

    我喜欢这个INDEX。谢谢。希望它有所帮助。

2 个答案:

答案 0 :(得分:3)

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

要获得更好的性能,您需要使用SPATIAL索引,如this article中所述。

答案 1 :(得分:0)

尝试在查询中包含的所有字段上创建索引。在这个特殊情况下,在两个字段(start_ip和end_ip)上创建一个索引