2

このクエリの実行には0.0002 秒かかります。

SELECT country,city
FROM location
WHERE locID = 30296
LIMIT 1

locID は明らかに INDEX です。

この他のクエリはルーチンを使用し、実行に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 ;
4

2 に答える 2

3

前の回答が反対票を投じられた理由はわかりませんが、彼/彼は正しかったです。location次の理由により、関数はテーブル内のすべての行に対して実行されます。

  • [NOT] DETERMINISTIC関数定義に句が指定されていNOT DETERMINISTICないため、
  • LIMITすべての行がすでにスキャンされ、それぞれのWHERE条件がチェックされている場合、句はプロセスの最後に適用されます。

すべての行が最終的にスキャンされるため、オプティマイザーがインデックスを使用しないことにしたとしても、私は驚かないでしょう。これは、EXPLAIN

関数を として再定義する場合は、驚きを避けるために句DETERMINISTICも追加してください。READS SQL DATA

ところで、この関数は、その結果に関してナンセンスです。これは代わりにビューとして実装する必要があります (そうすれば問題は発生しません)。

于 2013-06-28T00:40:26.653 に答える
0

クエリを実行すると、最初に SELECT が実行され、その後に WHERE が実行され、SELECT のフィルター処理が開始されます。このため、クエリでは、すべての SELECT 行で IPTOLOCID 関数が実行され、データが出力されます。

于 2013-06-28T00:28:42.880 に答える