MySQL: не следует ли использовать процедуру для поиска соответствия в этом примере намного быстрее?
Этот запрос занимает 0,0002 секунды для выполнения:
SELECT country,city
FROM location
WHERE locID = 30296
LIMIT 1
Очевидно, что locID это ИНДЕКС.
Этот другой запрос использует подпрограмму и занимает 0,0005 секунд для выполнения (он возвращает 30296):
SELECT IPTOLOCID(
'190.131.60.58'
)
Тогда почему этот комбинированный запрос занимает 1,7912 с для выполнения? Кажется, гораздо больше, чем должно быть:
SELECT country, city
FROM location
WHERE locID = IPTOLOCID('190.131.60.58')
LIMIT 1
На тот случай, если вы найдете это полезным, это таблицы и процедура:
CREATE TABLE `blocks` (
`startIPNum` int(10) unsigned NOT NULL,
`endIPNum` int(10) unsigned NOT NULL,
`locID` int(10) unsigned NOT NULL,
PRIMARY KEY (`startIPNum`,`endIPNum`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 PACK_KEYS=1 DELAY_KEY_WRITE=1;
CREATE TABLE `location` (
`locID` int(10) unsigned NOT NULL,
`country` char(2) default NULL,
`region` char(2) default NULL,
`city` varchar(45) default NULL,
`postalCode` char(7) default NULL,
`latitude` double default NULL,
`longitude` double default NULL,
`dmaCode` char(3) default NULL,
`areaCode` char(3) default NULL,
PRIMARY KEY (`locID`),
KEY `Index_Country` (`country`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED;
DELIMITER $$
DROP FUNCTION IF EXISTS `IPTOLOCID` $$
CREATE FUNCTION `IPTOLOCID`( ip VARCHAR(15)) RETURNS int(10) unsigned
BEGIN
DECLARE ipn INTEGER UNSIGNED;
DECLARE locID_var INTEGER;
IF ip LIKE '192.168.%' OR ip LIKE '10.%' THEN
RETURN 0;
END IF;
SET ipn = INET_ATON(ip);
SELECT locID INTO locID_var
FROM `blocks`
INNER JOIN
(SELECT MAX(startIPNum) AS start
FROM `blocks`
WHERE startIPNum <= ipn) AS s
ON (startIPNum = s.start)
WHERE endIPNum >= ipn;
RETURN locID_var;
END $$
DELIMITER ;
2 ответа
Я не знаю, почему предыдущий ответ был отвергнут, но он / она был прав. Функция выполняется для каждой строки в вашем location
таблица, потому что:
- нет
[NOT] DETERMINISTIC
пункт был предоставлен в определении функции, поэтомуNOT DETERMINISTIC
предполагается -
LIMIT
Предложение применяется в самом конце процесса, когда все строки уже отсканированы, иWHERE
условие было проверено для каждого из них
Я не удивлюсь, если оптимизатор решит не использовать индекс, потому что все строки будут в конечном итоге сканироваться. Вы можете проверить это с EXPLAIN
Если вы переопределите свою функцию как DETERMINISTIC
также добавьте READS SQL DATA
пункт, чтобы избежать каких-либо сюрпризов.
Кстати, эта функция не имеет смысла в отношении ее результата. Это должно быть реализовано в виде представления (тогда проблема не будет применяться).
Когда вы запускаете запрос, сначала происходит SELECT, а затем ГДЕ приходит и начинает фильтровать SELECT. Из-за этого в вашем запросе каждая строка SELECT запускает вашу функцию IPTOLOCID, а затем выводит ваши данные.