底部的表格定义。对于一组极其快速的随机唯一 ID:
with r as (
select distinct
ceil(
random() *
(select max(image_id) from image)
)::int as image_id
from generate_series(1, 200)
limit 100
)
select image_id
from image inner join r using (image_id)
limit 50
由于主键有间隙,因此需要将表连接到超过 50 个随机生成的 id 以确保至少有 50 个。还有多少将取决于 PK 的“间隙”。在示例表中,每 5 个缺少 2 个。
要获得不同的随机生成的 id,还需要生成多于(在上面的示例中)要加入的 100 个。还有多少取决于桌子有多大。对于一个非常大的桌子来说,再多几个就足够了。
即使上面的数字被夸大了,对性能的影响也可以忽略不计。为了让它不返回看起来像的图像,我将创建一个 seem_images 表,其中包含 session_id(或 user_id 用于更长的到期时间)和 image_id 并在每个 GetImages 处插入。无需额外功能GetMoreImages。
with r as (
select distinct
ceil(
random() *
(select max(image_id) from image)
)::int as image_id
from generate_series(1, 200)
limit 100
), t as (
select image_id, image
from image inner join r using (image_id)
where not exists (
select 1
from seem_image
where image_id = image.image_id and session_id = 1
)
limit 50
), i as (
insert into seem_image (image_id, session_id)
select image_id, 1
from t
)
select * from t;
上面的查询只会返回不看起来的图像。对于样本 300 万行 image 表,它非常快。对于长图像浏览和会话,有必要从上面的100 和200 更改为适当的数字。过期会话应定期从seem_image 表中删除,具体取决于会话过期时间,以避免它变得太大。
示例image(以整数作为主键,有间隙)和seem_image 表
create table image (
image_id integer primary key,
image bytea
);
insert into image (image_id, image)
select image_id, image
from
generate_series(1, 5000000) g (image_id)
cross join
(values (decode(rpad('', 1024 * 100, 'F'), 'hex'))) i (image)
where mod (image_id, 5) not in (0, 1)
;
analyze image;
create table seem_image (
session_id integer,
image_id integer,
primary key (image_id, session_id)
);