MYSQL - 在范围内快速搜索的结果之间的限制

时间:2016-07-23 11:31:50

标签: mysql range between

我在MYSQL中有两个表,其中table2包含17位数字(varchar 17)的序列号范围(唯一),table1包含序列值(格式与范围相同) 例如:

table 1:
serial_id   seial
1           12345678123456799

table 2:
range id      date              start                end
1             2012-01-01        12345678123456789    12345678123456999
2             2012-01-01        12345678123457000    12345678123457099
3             2012-01-01        12345678123457100    12345678123457199

我想找到每个序列都属于它的范围ID。可以使用的最简单的查询是:

select *
from table1,table2
where table1.serial  between table2.start and table2.end 

但我希望通过以下事实优化它以更快地运行: 序列号和范围是唯一的,因此每个序列可能属于一个且只有一个范围。所以当一个范围包含序列时,没有必要搜索其他范围。 每个范围的前11位数字是相同的。例如,一个范围可以是12345678120000000到12345678129999999。 连续出版物和范围按日期排序,更有可能在早期查找范围。连续出版物约有6000000条记录,范围约为100000条记录。

任何更好查询的想法?

2 个答案:

答案 0 :(得分:0)

这对加速来说有点挑战。以下是我使用IP地址范围的一种方法:

select t1.*,
       (select t2.range_id
        from table2 t2
        where t2.start <= t.serial
        order by t2.start desc
        limit 1
       ) as range_id
from table1 t1;

这可以利用table2(start, range_id)上的索引。

注意:这不会检查范围的结尾。为此,我会添加另一个连接。 。 。虽然这(不幸)需要实现子查询:

select *
from (select t1.*,
             (select t2.range_id
              from table2 t2
              where t2.start <= t.serial
              order by t2.start desc
              limit 1
             ) as range_id
      from table1 t1
     ) t1 left join
     table2 t2
     on t1.range_id = t2.range_id and t2.end >= t.serial;

其他加入需要table2(range_id, end)上的索引。

答案 1 :(得分:0)

我认为通过数据模型的一点变化,将会出现很大的性能提升。 通过将rangeid列添加到table1作为外键。

table 1:
serial_id   seial              rangeid
1           12345678123456799  1

然后写下面的查询:

select *
from table1 join table2 using(rangeid);

如果无法进行更改,您可以使用like运算符,如下所示:

select *
from table1 join table2
on(table2.start like concat(left(table1.serial,12),'%'))
where table1.serial  between table2.start and table2.end;

table2.start列必须编入索引。

编辑: 根据序列字段和开始字段之间的关系,将数字“12”增加到最大可能数。