我的mySQL查询是否尽可能高效?

时间:2011-07-15 13:08:45

标签: mysql

我有一个mySQL查询,需要很长时间才能处理。我正在查询与国家/地区代码相关的大范围IP表,以便在url_click表中发现每个IP的原始国家/地区。 (来自hxxp的IP数据库://ip-to-country.webhosting.info/)

虽然很慢,但效果非常好。

有没有更有效的方法来编写此查询?

表格和输出JPG:http://tiny.cx/a4e00d

SELECT ip_addr AS IP, geo_ip.ctry, count(ip_addr) as count
FROM `admin_adfly`.`url_click`,admin_adfly.geo_ip
WHERE INET_ATON (ip_addr) 
BETWEEN geo_ip.ipfrom AND geo_ip.ipto 
AND url_id = 165 
GROUP BY ip_addr;

4 个答案:

答案 0 :(得分:0)

IP地址具有树状结构,并且geo_ip表中的范围很可能与该结构相符。

如果您的IP以193.167开头,那么您应该有一个索引可以帮助您快速过滤geo_ip表,以便只处理与193.167子范围相关的行。

我认为你应该能够通过这种方法显着改善响应时间。

我希望这会对你有所帮助

答案 1 :(得分:0)

INET_ATON让我有点担心。它会使ip_addr列上的任何索引无效。如果您有一种方法可以将信息全部放在相同的格式中,比如在将数据放入数据库之前将数据转换为数字,这可能会有所帮助。

除此之外,有关明智使用索引的标准建议适用。您可能希望在ipfromipto和/或url_id列上建立索引。

答案 2 :(得分:0)

MySQL不会优化此类查询。

您需要将ipfrom-ipto范围转换为LineStrings,从而允许在其上构建R-Tree索引:

ALTER TABLE
        geo_ip
ADD     range LINESTRING;

UPDATE  geo_ip 
SET     range = LINESTRING(POINT(-1, ipfrom), POINT(1, ipfrom));

ALTER TABLE
        geo_ip
MODIFY  range LINESTRING NOT NULL;

CREATE SPATIAL INDEX
        sx_geoip_range
ON      geo_ip (range); 

SELECT  ip_addr AS IP, geo_ip.ctry, COUNT(*)
FROM    `admin_adfly`.`url_click`
JOIN    admin_adfly.geo_ip
ON      MBRContains
                (
                Point(0, INET_ATON (ip_addr)),
                range
                )
WHERE   url_id = 165 
GROUP BY
        ip_addr

geo_ip应为MyISAM表。

请点击此处了解更多详情:

答案 3 :(得分:0)

在两个表之间的连接中使用函数将比正常连接慢,因此您可能希望尽可能延迟该特定操作。所以,我总结了数据,然后加入它:

SELECT S.IP_Addr, G.Ctry AS Country, S.Count
  FROM (SELECT ip_addr, COUNT(ip_addr) AS Count
          FROM admin_adfly.url_click 
         WHERE url_id = 165 
         GROUP BY ip_addr) AS S
  JOIN admin_adfly.geo_ip AS G
    ON INET_ATON (ip_addr) BETWEEN geo_ip.ipfrom AND geo_ip.ipto;

如果您可以重新设计架构并且将要进行大量此分析,请重新编写两个表中的一个,以便连接条件不需要使用INET_ATON()。

据推测,您在url_id列上有一个索引;这是唯一一个能给你带来很多好处的东西。