MySQL 比较查询性能
MySQL compare query performance
我在 MySQL 中有一个 table 是这样的:
startIp
endIp
城市
国家代码
纬度
经度
16777216
16777471
洛杉矶
美国
34.0522
-118.244
16777472
16778239
福州
CN
26.0614
119.306
16778240
16779263
墨尔本
澳大利亚
-37.814
144.963
还有 270 万个条目。
现在我有一个像 16777566 这样的转换后的 IP 地址。
这应该 return "Fuzhou, CN, 26.0614, 119.306"
现在我使用这个查询:
SELECT * 从 <code>kombiniert
WHERE startIp < 16777566 AND endIp > 16777566
它工作得很好,但速度很慢。
性能:
没有限制:SELECT * FROM <code>kombiniert
WHERE startIp < 2264918979 AND endIp > 2264918979;
平均(2300 毫秒)
有限制:SELECT * FROM <code>kombiniert
WHERE startIp < 2264918979 AND endIp > 2264918979 LIMIT 1;
平均(1500 毫秒)
无限制索引:SELECT * FROM <code>kombiniert
WHERE startIp < 2264918979 AND endIp > 2264918979;
平均(5300 毫秒)
索引限制:SELECT * FROM <code>kombiniert
WHERE startIp < 2264918979 AND endIp > 2264918979 LIMIT 1;
平均(5500 毫秒)
现在我想加快这个查询!我为什么要这样做?
非常感谢!
编辑:我忘了说:字段 startIp、endIp 是 bigint!
EDIT2:table 创建 sql:
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
CREATE TABLE `kombiniert` (<br>
`id` int(11) NOT NULL,<br>
`startIp` bigint(20) NOT NULL,<br>
`endIp` bigint(20) NOT NULL,<br>
`city` text NOT NULL,<br>
`countryCode` varchar(4) NOT NULL,<br>
`latitude` float NOT NULL,<br>
`longitude` float NOT NULL<br>
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;<br>
<br>
ALTER TABLE `kombiniert`<br>
ADD PRIMARY KEY (`id`),<br>
ADD KEY `startIp` (`startIp`),<br>
ADD KEY `endIp` (`endIp`);<br>
<br>
ALTER TABLE `kombiniert`<br>
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2747683;<br>
COMMIT;<br>
搜索 IP 地址(或任何其他分成桶的指标)效率不高。或者至少对明显的代码效率不高。您可以获得的最佳平均性能是扫描四分之一的 table 以查找您要查找的内容。那就是“订单(N)”。
您可以获得大多数操作的“Order(1)”性能,但它需要重组 table 和查询。参见 http://mysql.rjweb.org/doc.php/ipranges
我在 MySQL 中有一个 table 是这样的:
startIp | endIp | 城市 | 国家代码 | 纬度 | 经度 |
---|---|---|---|---|---|
16777216 | 16777471 | 洛杉矶 | 美国 | 34.0522 | -118.244 |
16777472 | 16778239 | 福州 | CN | 26.0614 | 119.306 |
16778240 | 16779263 | 墨尔本 | 澳大利亚 | -37.814 | 144.963 |
还有 270 万个条目。
现在我有一个像 16777566 这样的转换后的 IP 地址。
这应该 return "Fuzhou, CN, 26.0614, 119.306"
现在我使用这个查询:
SELECT * 从 <code>kombiniert
WHERE startIp < 16777566 AND endIp > 16777566
它工作得很好,但速度很慢。
性能:
没有限制:SELECT * FROM <code>kombiniert
WHERE startIp < 2264918979 AND endIp > 2264918979;
平均(2300 毫秒)
有限制:SELECT * FROM <code>kombiniert
WHERE startIp < 2264918979 AND endIp > 2264918979 LIMIT 1;
平均(1500 毫秒)
无限制索引:SELECT * FROM <code>kombiniert
WHERE startIp < 2264918979 AND endIp > 2264918979;
平均(5300 毫秒)
索引限制:SELECT * FROM <code>kombiniert
WHERE startIp < 2264918979 AND endIp > 2264918979 LIMIT 1;
平均(5500 毫秒)
现在我想加快这个查询!我为什么要这样做?
非常感谢!
编辑:我忘了说:字段 startIp、endIp 是 bigint!
EDIT2:table 创建 sql:
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
CREATE TABLE `kombiniert` (<br>
`id` int(11) NOT NULL,<br>
`startIp` bigint(20) NOT NULL,<br>
`endIp` bigint(20) NOT NULL,<br>
`city` text NOT NULL,<br>
`countryCode` varchar(4) NOT NULL,<br>
`latitude` float NOT NULL,<br>
`longitude` float NOT NULL<br>
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;<br>
<br>
ALTER TABLE `kombiniert`<br>
ADD PRIMARY KEY (`id`),<br>
ADD KEY `startIp` (`startIp`),<br>
ADD KEY `endIp` (`endIp`);<br>
<br>
ALTER TABLE `kombiniert`<br>
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2747683;<br>
COMMIT;<br>
搜索 IP 地址(或任何其他分成桶的指标)效率不高。或者至少对明显的代码效率不高。您可以获得的最佳平均性能是扫描四分之一的 table 以查找您要查找的内容。那就是“订单(N)”。
您可以获得大多数操作的“Order(1)”性能,但它需要重组 table 和查询。参见 http://mysql.rjweb.org/doc.php/ipranges