我有一個包含名稱,電子郵件地址和IP的1500萬條記錄的表。我需要使用IP地址更新同一個表中國家代碼的另一列。我下載了一個包含所有IP範圍和相關國家的小型數據庫(ip2location lite - https://lite.ip2location.com/)。 ip2location表具有以下結構;如何優化此範圍查詢
CREATE TABLE `ip2location_db1` (
`ip_from` int(10) unsigned DEFAULT NULL,
`ip_to` int(10) unsigned DEFAULT NULL,
`country_code` char(2) COLLATE utf8_bin DEFAULT NULL,
`country_name` varchar(64) COLLATE utf8_bin DEFAULT NULL,
KEY `idx_ip_from` (`ip_from`),
KEY `idx_ip_to` (`ip_to`),
KEY `idx_ip_from_to` (`ip_from`,`ip_to`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin
我使用以下函數從ip地址檢索國家代碼;
CREATE DEFINER=`root`@`localhost` FUNCTION `get_country_code`(
ipAddress varchar(30)
) RETURNS VARCHAR(2)
DETERMINISTIC
BEGIN
DECLARE ipNumber INT UNSIGNED;
DECLARE countryCode varchar(2);
SET ipNumber = SUBSTRING_INDEX(ipAddress, '.', 1) * 16777216;
SET ipNumber = ipNumber + (SUBSTRING_INDEX(SUBSTRING_INDEX(ipAddress, '.', 2),'.',-1) * 65536);
SET ipNumber = ipNumber + (SUBSTRING_INDEX(SUBSTRING_INDEX(ipAddress, '.', -2),'.',1) * 256);
SET ipNumber = ipNumber + SUBSTRING_INDEX(ipAddress, '.', -1);
SET countryCode =
(SELECT country_code
FROM ip2location.ip2location_db1
USE INDEX (idx_ip_from_to)
WHERE ipNumber >= ip2location.ip2location_db1.ip_from AND ipNumber <= ip2location.ip2location_db1.ip_to
LIMIT 1);
RETURN countryCode;
END$$
DELIMITER ;
我已經運行了EXPLAIN語句,這是輸出;
'1', 'SIMPLE', 'ip2location_db1', NULL, 'range', 'idx_ip_from_to', 'idx_ip_from_to', '5', NULL, '1', '33.33', 'Using index condition'
我的問題是,1000條記錄查詢採用15S〜執行這意味着運行在所有數據庫中的相同的查詢將需要超過2天就可以完成。有沒有辦法來改善這個查詢。
PS - 如果我刪除了USE INDEX(idx_ip_from_to),查詢需要兩倍的時間。你能解釋爲什麼嗎?
而且我不是一個數據庫專家,所以容忍我:)
表格是否有重疊範圍?如果是這樣,你不能優化它(即使戈登的建議)。 –
不要對'country_code'使用'utf8' - 只需要2個時需要6個字節;使用'ascii'。 –
IPv6怎麼樣? –