质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数。
100以内的质数总共有25个
2、3、5、7、11、13、17、19、23、29、31、37、41、43、47、53、59、61、67、71、73、79、83、89、97
了解一下质数是什么以后开始讨论我遇到的一些问题。
1.需求介绍
简化一下需求,需要对一系列图片进行打标签并将结果记录在数据库当中,方便根据标签查询图片。请问怎么设计这个数据库表结构。
2.设计实现
标签和图片之间是一个多对多的关系,那么就需要三张表,标签表(Tag),图片表(Image)和标签图片关联表(ImgTagRes)。
CREATE TABLE `tag` (
`Id` int(11) NOT NULL,
`Name` varchar(255) ,
PRIMARY KEY (`Id`) USING BTREE
)
CREATE TABLE `image` (
`Id` int(11) NOT NULL,
`Name` varchar(255) ,
PRIMARY KEY (`Id`) USING BTREE
)
CREATE TABLE `imagetagres` (
`tagid` int(11) NOT NULL,
`imgid` int(11) NOT NULL,
PRIMARY KEY (`Id`) USING BTREE
)
#获取所有打了2标签的图片
select imgid from imagetagres where tagid = 2
#获取所有同时打了2和3标签的图片
select imgid from imagetagres where tagid in (2,3)
Group by imgid Having count(*) =2
那么有没有别的实现方式了呢?感觉表还是太多了,能不能把关联表给删除了,只要一个图片表一个标签表?
当然,不需要把标签Id拼接然后存放到图片表字段中的处理方式,毕竟也要保证查询时候的效率的。
3.质数分解法
当一个数字是由多个质数相乘而成的时候。如105=3 * 5 * 7
,那么对这个数字进行质因数分解,也只会由这几个数字构成。话说回来,这个理论如何应用在这个地方呢?
首先构建标签表的时候,++所有标签的Id都用质数替代(2、3、5、7....)
。同时在图片表中,新增一个Tag
字段记录给他打的所有标签的Id乘积。++
#获取所有打了2标签的图片
select ImgId from Image where Mod(Tag,2) = 0
#获取所有同时打了2和3标签的图片
select ImgId from Image where Mod(Tag,2*3) = 0
速度真的超级快。
质数相乘取代关联表的缺陷
1.质数乘积是有使用限制的,当多个质数相乘的时候,很容易一不小心就爆掉int.MaxValue
甚至是long.MaxValue
。
2.无法快速反向获取到数字是由哪几个质因数乘积构成的。(当然可以通过加字段记录下,或者维护一个质因数序列来分解质因数)
总结
不是所有的多对多关系都可以使用这种方式的,这里只是提供一个思路,在一些特定场景下可以采用这种方法。继续使用上面的标签来举这个例子:
1.标签数量是相对比较固定的,且个数不会很多。
2.对图片打标签的时候,有个数限制,尽量不要出现对一个图片打很多标签,导致最后的乘积超出int.MaxValue
的情况出现