在pri_key连贯与pri_key非连贯的表数据中实现随机查询

有时候我们会遇到对单个表或者多个表进行随机查询,但是如果使用SELECT * FROM table ORDER BY RAND() LIMIT 1这样的方法,效率和性能都非常的差。也许我们可以换个方式方法来实现。

primary_key 是连贯的数据表

primary_key连贯,意思是数据表的主键是连贯的,例如1,2,3,4,5,6。这样的查询就非常的简单,我们只需要得到这张表的总count,通过程序来随机一个primary_key,再通过这个primary_key直接查询就好了。

1
2
3
4
5
# 随机users表
primary_key = rand(1..User.count)
if User.exists?(primary_key)
user = User.find(primary_key)
end

primary_key 非连贯的数据表

primary_key非连贯,意思是数据表的主键并不是连贯的,当然这样的情况在生产环境中更为多见,例如1,2,6,16,24,35。这样的查询就无法直接随机主键ID来实现了。我们可以建立一张随机关联表relations,通过relations表的外键来关联主键ID,因为我们relations的主键ID是连贯的,所以只需要随机relations表的主键ID,就能得到我们希望随机的数据。而且这样的方案可以实现多个不同表的随机。

1
2
3
4
5
6
7
+-----------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| origin_id | int(11) | YES | | 0 | |
| origin_table_id | int(11) | YES | | 0 | |
+-----------------+----------+------+-----+---------+----------------+

其中origin_idusersarticles的外键,可以重复,origin_table_id用来区分origin_id是哪张表的外键,比如我们设定1 => users2 => articles

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 随机users表、articles表
relation_id = rand(1..Relation.count)
relation = Relation.find(relation_id)
case relation.origin_table_id
when 1
if User.exists?(relation.origin_id)
user = User.find(relation.origin_id)
end
when 2
if Article.exists?(relation.origin_id)
article = Article.find(relation.origin_id)
end
end