我试图了解是否有任何标准的最佳实践方法来建模关系数据库中的数字范围(在本例中为MySQL),如果这实际上是一件明智的事情。
我将解释提出问题的任务。
我目前正在设计一个数据库,该数据库将为客户分配标识符池。
潜在标识符池的范围为0到大约2 ^ 30
可以为给定客户分配从单个标识符到多个连续块中的数百万个的任意数量的标识符。
给定的标识符只能分配给单个客户(即它是一对多关系)
显然,将有一个Customer表和一个包含Customer键的Identifier表。
复杂性来自于如何为标识符建模:
选项一是使用一行代表单个标识符。这将导致表中可能存在大量行,但会搜索谁拥有哪个标识符以及给定标识符是否正在使用中。
第二个(我认为更有前途的)选项是让一行代表一系列具有最小值和最大值的值。这会使查询变得更复杂(我假设用于检查标识符是否正在使用的查询将查询“最小值低于X”和“最大值高于X”的范围)但是会导致远行数减少,可能更容易管理和更新。
我欢迎任何关于这是否是一种好方法的观点,如果没有明显更好的方法,我会很高兴。
答案 0 :(得分:7)
如果范围不相交,则可以将它们存储为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
答案 1 :(得分:2)
如果我理解正确,你需要使用多个范围,这可能会变得棘手。您可能想要查看PostgreSQL 9.2范围类型。它们看起来与你想要做的事情有关。
在现实世界中,范围可以重叠,相互包含或不重叠,并且可以打开或关闭,使得范围检查查询可能很复杂且容易出错。范围类型消除了大部分这种复杂性,并且它们通过索引原生支持。
https://wiki.postgresql.org/images/7/73/Range-types-pgopen-2012.pdf
祝福,
尼克
答案 2 :(得分:1)
通常,我不会仅仅为了它而尝试减少行数 - 原则上,具有十亿行的索引良好的表应该与具有100行的表一样快,只要您的查询命中了索引。
我会更多地研究您可能想要运行的实际查询,并在此基础上设计解决方案。例如,您是否要列出属于单个客户的所有ID?您想检查哪个客户拥有多个ID吗?您想要查找客户拥有的ID数量吗?
如果你有“范围”表,后者有点棘手 - 而不是做"select count(*) from ranges where customer = 1"
,你必须计算客户每个范围内的IP数,然后加上它们。不是火箭科学,但在现实世界中可能会更慢......
答案 3 :(得分:0)
如果你像这样制作一张桌子
表格ID
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)
答案 4 :(得分:0)
一种可能性是使用正则表达式来表示标识符池,根据需要在字符串和数字之间进行转换。这里的问题是为给定的标识符列表找到正则表达式。这可以使用Aho-Corasick算法自动完成。只有当这些ID池看起来大致相同时,这才是实用的。显然,如果它们是随机分配的,那么很难找到比一长列ORd文字更好的正则表达式。