Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 在数据库表中查找范围内的值_Mysql - Fatal编程技术网

Mysql 在数据库表中查找范围内的值

Mysql 在数据库表中查找范围内的值,mysql,Mysql,我需要的SQL等效于 我有一张这样的桌子 ID MN MX -- -- -- A 0 3 B 4 6 C 7 9 给定一个数字,比如说5,我想找到MN和MX包含该数字的行的ID,在本例中是B 显然, SELECT ID FROM T WHERE ? BETWEEN MN AND MX 可以,但我有900万行,我希望它运行得尽可能快。特别是,我知道只能有一个匹配行,我现在知道MN-MX范围完全覆盖了空间,等等。有了所有这些对可能答案的限制,我应该可以做一些优化。不应该有吗 到目前为

我需要的SQL等效于

我有一张这样的桌子

ID MN MX
-- -- --
A  0  3
B  4  6
C  7  9
给定一个数字,比如说5,我想找到MN和MX包含该数字的行的ID,在本例中是B

显然,

SELECT ID FROM T WHERE ? BETWEEN MN AND MX
可以,但我有900万行,我希望它运行得尽可能快。特别是,我知道只能有一个匹配行,我现在知道MN-MX范围完全覆盖了空间,等等。有了所有这些对可能答案的限制,我应该可以做一些优化。不应该有吗

到目前为止,我所拥有的只是索引MN并使用以下内容

SELECT ID FROM T WHERE ? BETWEEN MN AND MX ORDER BY MN LIMIT 1

但这是很弱的。

如果您的集合中没有空白,那么简单的gte比较就可以了:

SELECT ID FROM T WHERE ? >= MN ORDER BY MN ASC LIMIT 1

如果您有一个跨越MN和MX的索引,它应该非常快,即使有9M行

alter table T add index mn_mx (mn, mx);
编辑

我刚试过一个测试,有一个1米长的表格

mysql> select count(*) from T;
+----------+
| count(*) |
+----------+
|  1000001 |
+----------+
1 row in set (0.17 sec)

mysql> show create table T\G
*************************** 1. row ***************************
       Table: T
Create Table: CREATE TABLE `T` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `mn` int(10) DEFAULT NULL,
  `mx` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `mn_mx` (`mn`,`mx`)
) ENGINE=InnoDB AUTO_INCREMENT=1048561 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> select * from T order by rand() limit 1;
+--------+-----------+-----------+
| id     | mn        | mx        |
+--------+-----------+-----------+
| 112940 | 948004986 | 948004989 |
+--------+-----------+-----------+
1 row in set (0.65 sec)

mysql> explain select id from T where 948004987 between mn and mx;
+----+-------------+-------+-------+---------------+-------+---------+------+--------+--------------------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows   | Extra                    |
+----+-------------+-------+-------+---------------+-------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | T     | range | mn_mx         | mn_mx | 5       | NULL | 239000 | Using where; Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+--------+--------------------------+
1 row in set (0.00 sec)

mysql> select id from T where 948004987 between mn and mx;
+--------+
| id     |
+--------+
| 112938 |
| 112939 |
| 112940 |
| 112941 |
+--------+
4 rows in set (0.03 sec)
在我的例子中,我只是有一个mn值的递增范围,然后将mx设置为+3,这就是为什么我得到了大于1的值,但应该对您应用相同的值

编辑2

修改您的查询肯定会更好

mysql> explain select id from T where mn<=947892055 and mx>=947892055;
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
|  1 | SIMPLE      | T     | range | mn_mx         | mn_mx | 5       | NULL |    9 | Using where; Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
mysql>解释从T选择id,其中mn=947892055;
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
|id |选择|类型|类型|可能的|键|键|列|参考|行|额外|
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
|1 |简单| T |范围| mn|uMX | mn|uMX | 5 |空| 9 |使用where;使用索引|
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+

值得注意的是,尽管第一个
explain
报告了更多要扫描的行,但我已经设置了足够的innodb缓冲池,以便在创建之后将整个内容保存在RAM中;所以还是很快。

好吧,你可以改变
?在MN和MX之间
MN>=?
,或者按MN限制1删除
订单(但显然不是两者都有)。但是您当前的查询有什么“薄弱”之处?如果不知道你不喜欢什么,就很难知道该建议什么替代方案。目前的查询时间是多少?两者之间的距离相当快。您是否对您的查询运行了
explain
,以查看MySQL将如何执行查询的详细信息?@MikePurcell-我还没有这样做。我只是想知道在如何做这样的事情上是否有集体智慧。奇怪的是,在替换
之间的时,我没有在扫描的行中得到相同的下降。事实上,即使是索引似乎也没有实际加速多少(在0.06到0.15秒之间)。桌子最终比我预想的要小得多,我想这一切都在记忆中。