GeoIP table join with table of IP's in MySQL

前端 未结 4 1734
终归单人心
终归单人心 2021-01-02 23:38

I am having a issue finding a fast way of joining the tables looking like that:

mysql> explain geo_ip;
+--------------+------------------+------+-----+---         


        
4条回答
  •  迷失自我
    2021-01-03 00:05

    Just wanted to give back to the community:

    Here's an even better and optimized way building on Aleksi's solution:

    DROP PROCEDURE IF EXISTS recalculate_ip_geolocation_lookup;
    
    DELIMITER ;;
    CREATE PROCEDURE recalculate_ip_geolocation_lookup()
    BEGIN
      DECLARE i INT DEFAULT 0;
    DROP TABLE `ip_geolocation_lookup`;
    
    CREATE TABLE `ip_geolocation_lookup` (
      `first_octet` smallint(5) unsigned NOT NULL DEFAULT '0',
      `startIpNum` int(10) unsigned NOT NULL DEFAULT '0',
      `endIpNum` int(10) unsigned NOT NULL DEFAULT '0',
      `locId` int(11) NOT NULL,
      PRIMARY KEY (`first_octet`,`startIpNum`,`endIpNum`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    INSERT IGNORE INTO ip_geolocation_lookup
    SELECT  startIpNum DIV 1048576 as first_octet, startIpNum, endIpNum, locId
    FROM ip_geolocation;
    
    INSERT IGNORE INTO ip_geolocation_lookup
    SELECT  endIpNum DIV 1048576 as first_octet, startIpNum, endIpNum, locId
    FROM ip_geolocation;
    
      WHILE i < 1048576 DO
        INSERT IGNORE INTO ip_geolocation_lookup
            SELECT i, startIpNum, endIpNum, locId 
            FROM ip_geolocation_lookup 
            WHERE first_octet = i-1
            AND endIpNum DIV 1048576 > i;
       SET i = i + 1;
      END WHILE;
    END;;
    DELIMITER ;
    
    CALL recalculate_ip_geolocation_lookup();
    

    It builds way faster than his solution and drills down more easily because we're not just taking the first 8, but the first 20 bits. Join performance: 100000 rows in 158ms. You might have to rename the table and field names to your version.

    Query by using

    SELECT ip, kl.*
    FROM random_ips ki
    JOIN `ip_geolocation_lookup` kb ON (ki.`ip` DIV 1048576 = kb.`first_octet` AND ki.`ip` >= kb.`startIpNum` AND ki.`ip` <= kb.`endIpNum`)
    JOIN ip_maxmind_locations kl ON kb.`locId` = kl.`locId`;
    

提交回复
热议问题