【问题标题】:Optimizing MySQL query for integer range search优化 MySQL 查询以进行整数范围搜索
【发布时间】:2013-10-18 18:24:14
【问题描述】:

我在一个表中有超过 170 万条记录,其中包含 ip 地址范围(开始和结束)以及主键和相应的详细信息。

表结构是

mysql> desc csv;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| begin   | bigint(20)  | NO   | PRI | 0       |       |
| end     | bigint(20)  | NO   | PRI | 0       |       |
| code    | char(2)     | YES  |     | NULL    |       |
| country | varchar(50) | YES  |     | NULL    |       |
| city    | varchar(50) | YES  |     | NULL    |       |
| area    | varchar(50) | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+

由于主键中的索引,当要进行精确匹配时,搜索速度很快

mysql> SELECT * FROM csv WHERE begin=3338456576;
+------------+------------+------+---------------+----------+---------------+
| begin      | end        | code | country       | city     | area          |
+------------+------------+------+---------------+----------+---------------+
| 3338456576 | 3338456831 | US   | UNITED STATES | NEW YORK | NEW YORK CITY |
+------------+------------+------+---------------+----------+---------------+
1 row in set (0.03 sec)

但是当我尝试在一个范围内搜索时,它需要更长的时间。

mysql> SELECT * FROM csv WHERE begin<3338456592 AND end>3338456592;
+------------+------------+------+---------------+----------+---------------+
| begin      | end        | code | country       | city     | area          |
+------------+------------+------+---------------+----------+---------------+
| 3338456576 | 3338456831 | US   | UNITED STATES | NEW YORK | NEW YORK CITY |
+------------+------------+------+---------------+----------+---------------+
1 row in set (1.59 sec)

有什么方法可以优化我的查询以在一个范围内搜索 IP 地址?

编辑

建表语句

CREATE TABLE `csv` (
  `begin` bigint(20) NOT NULL DEFAULT '0',
  `end` bigint(20) NOT NULL DEFAULT '0',
  `code` char(2) DEFAULT NULL,
  `country` varchar(50) DEFAULT NULL,
  `city` varchar(50) DEFAULT NULL,
  `area` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`begin`,`end`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

【问题讨论】:

  • 能否也贴出create table语句的输出?还有一些解释语句输出?
  • 查询返回多少行?您能否发布“SELECT count(*) FROM csv WHERE begin3338456592;”的结果? ?
  • 真的只有一排吗?这意味着所有剩余的行都满足相反的条件begin &gt; 3338456592 AND end &lt; 3338456592。假设begin &lt;= end(我的假设是真的吗?),那么170万条记录肯定有begin = end = 3338456592,只有一行有begin &lt;&gt; 3338456592 AND end &lt;&gt; 3338456592,对吗?

标签: mysql indexing query-optimization


【解决方案1】:

如果 IP 范围不重叠,因此查询永远不会返回超过 1 行,您可以使用此:

SELECT q.*
FROM 
  ( SELECT csv.* 
    FROM csv
    WHERE csv.begin < 3338456592 
    ORDER BY csv.begin DESC
    LIMIT 1
  ) AS q
WHERE 3338456592 < q.end ;

不需要添加索引。将使用主索引。

【讨论】:

  • 太棒了!!在 0.06 秒内完成。谢谢
  • 删除最后一行也可以。结果是0.0 seconds
  • 保留最后一行。否则你可能会得到误报。
【解决方案2】:

如果范围重叠,您应该:

  • 将 ip 范围定义为 LineString 列
  • 在该列上定义空间索引
  • 使用几何“包含”查询

Efficient data model for range queries中查看更多信息

【讨论】:

    【解决方案3】:

    SELECT begin, end, code, country, city, area FROM csv WHERE begin &lt;&gt; 3338456592 HAVING begin NOT BETWEEN MIN(begin) AND MAX(end) 的得分是多少?

    UPD: 这是我的表结构版本。

    CREATE TABLE `csv` (
      `begin` INT(10) NOT NULL DEFAULT '0',
      `end` INT(10) NOT NULL DEFAULT '0',
      `code` char(2) DEFAULT NULL,
      `country` varchar(50) DEFAULT NULL,
      `city` varchar(45) DEFAULT NULL,
      `area` varchar(40) DEFAULT NULL,
      KEY `combined` (`begin`,`end`)
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
    

    我认为使用国家和代码作为 ENUM 会更快。

    【讨论】:

    • 对我来说这似乎是一个不可能的 SQL...begin = 3338456592 MIN(begin) = 0 MAX(begin) = 4294967295 和 begin 3338456592 不在这些值之间?
    • @GauravSharma 实际上我们无法尝试优化您的表结构。什么返回SELECT * FROM csv PROCEDURE ANALYSE();
    • @GauravSharma 你能把表引擎改成myisam吗?它比innodb
    • @GauravSharma emm UNSIGNED INT(10) 怎么样?
    • UNSIGNED INT 确实可以保持最大值关闭 4294967295 IP 255.255.255.255 你可以删除 (10) 这仅适用于 zerofill...我有时会看到这个 INT(11) without zerofill 不知道也许程序员认为 int 可以通过这种方式保存更大的值......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-28
    相关资源
    最近更新 更多