Un order by
sera toujours cher surtout si l'expression dans l'ordre par n'est pas indexée. Alors ne commandez pas. À la place, faites un décalage aléatoire dans le count()
comme dans vos requêtes, mais faites tout en même temps.
with t as (
select *
from
products p
inner join
images i using (productid)
where
prodtype = $sometype
)
select *
from t
offset floor(random() * (select count(*) from t))
limit 1
Cette version pourrait être plus rapide
with t as (
select *, count(*) over() total
from
products p
inner join
images i using (productid)
where
prodtype = $sometype
)
select *
from t
offset floor(random() * (select total from t limit 1))
limit 1