我试图了解是否有任何标准的最佳实践方法来建模关系数据库中的数字范围(在这种情况下是MySQL),如果这实际上是一件明智的事情。
我将解释引发上下文问题的任务。
我目前正在设计一个数据库,该数据库将为客户分配标识符池。
潜在标识符池的范围为0到大约2 ^ 30
可以为给定客户分配从单个标识符到多个连续块中的数百万个的任意数量的标识符。
给定的标识符只能分配给单个客户(即,它是一对多的关系)
显然,将有一个Customer表和一个包含Customer键的Identifier表。
复杂性来自于如何为标识符建模:
选项一是使用一行代表单个标识符。这将导致表中可能存在大量行,但会搜索谁拥有哪个标识符以及给定标识符是否在使用中是微不足道的。
第二个(我认为更有前途的)选项是让一行代表一系列具有最小值和最大值的值。这会使查询更复杂(我假设用于检查标识符是否正在使用的查询将查询“最小值低于X”和“最大值高于X”的范围)但是会导致远行数更少,可能更容易管理和更新。
我欢迎任何关于这是否是一个好方法的意见,如果没有,如果有一个明显更好的方法我错过了。
如果范围不相交,则可以将它们存储为成对 INT
值:
CREATE TABLE customer_range
(
customerId INT,
rgStart INT,
rgEnd INT,
PRIMARY KEY (customerId, rgStart),
UNIQUE KEY (rgStart)
)
要查询号码所属的客户,请使用以下命令:
SELECT customerId
FROM customer_range
WHERE rgStart <= $mynum
AND rgEnd >= $mynum
ORDER BY
rgStart DESC
LIMIT 1
如果范围不相交,则可以将它们存储为成对 INT
值:
CREATE TABLE customer_range
(
customerId INT,
rgStart INT,
rgEnd INT,
PRIMARY KEY (customerId, rgStart),
UNIQUE KEY (rgStart)
)
要查询号码所属的客户,请使用以下命令:
SELECT customerId
FROM customer_range
WHERE rgStart <= $mynum
AND rgEnd >= $mynum
ORDER BY
rgStart DESC
LIMIT 1
如果我理解你正确你需要使用多个范围,这可能会变得棘手。您可能想要查看PostgreSQL 9.2范围类型。它们看起来与您要做的事情相关。
在现实世界中,范围可以重叠,相互包含或不重叠,并且它们可以是开放的或封闭的,使得范围检查查询可能复杂且容易出错。范围类型消除了大部分这种复杂性,并且通过索引本机支持它们。
https://wiki.postgresql.org/images/7/73/Range-types-pgopen-2012.pdf
最好的祝愿,
缺口
通常情况下,我不会仅仅为了它而尝试减少行数 - 原则上,只要您的查询命中,具有十亿行的索引良好的表应该与具有100行的表一样快指数。
我会更多地研究您可能想要运行的实际查询,并在此基础上设计解决方案。例如,您是否要列出属于单个客户的所有ID?您想检查哪个客户拥有多个ID吗?您想要找到客户拥有的ID数量吗?
如果你有“范围”表,后者有点棘手 - 而不是做 "select count(*) from ranges where customer = 1"
,您必须为客户计算每个范围内的IP数量,然后将它们相加。不是火箭科学,但在现实世界中可能会更慢......
如果你做一个像这样的桌子
表ids
id_start not null unsigned integer /*not autoincrement!*/
id_end not null unsigned integer
customer_id unsigned integer not null
foreign key FK_customer (customer_id) REFERENCES customer.id
primary key (id_start, id_end)
key id_end (id_end)
现在您可以通过执行操作来检查免费密钥
SELECT count(*) as occupied FROM ids
WHERE 100 between id_start and id_end;
要检查自由范围吗
SELECT count(*) as occupied FROM ids
WHERE NOT ('$low' > id_end) AND NOT ('$high' < id_start)
一种可能性是使用正则表达式来表示标识符池,根据需要在字符串和数字之间进行转换。这里的问题是为给定的标识符列表找到正则表达式。这可以使用Aho-Corasick算法自动完成。只有当这些ID池看起来大致相同时,这才是实用的。显然,如果它们是随机分配的,那么很难找到比一长列ORd文字更好的正则表达式。