Большинство решений здесь направлены на то, чтобы избежать сортировки, но им все равно необходимо последовательно сканировать таблицу.
Существует также способ избежать последовательного сканирования, переключившись на индексное сканирование. Если вы знаете значение индекса вашей случайной строки, вы можете получить результат почти мгновенно. Проблема в том, как угадать значение индекса.
Следующее решение работает на PostgreSQL 8.4:
explain analyze select * from cms_refs where rec_id in
(select (random()*(select last_value from cms_refs_rec_id_seq))::bigint
from generate_series(1,10))
limit 1;
В приведенном выше решении вы предполагаете 10 различных случайных значений индекса из диапазона 0 .. [последнее значение id].
Число 10 произвольно - вы можете использовать 100 или 1000, так как оно (как ни удивительно) не оказывает большого влияния на время отклика
Существует также одна проблема - если у вас редкие идентификаторы , вы можете пропустить . Решение состоит в том, чтобы имел план резервного копирования :). В этом случае это чистый старый порядок запроса random (). Когда объединенный идентификатор выглядит так:
explain analyze select * from cms_refs where rec_id in
(select (random()*(select last_value from cms_refs_rec_id_seq))::bigint
from generate_series(1,10))
union all (select * from cms_refs order by random() limit 1)
limit 1;
Не предложение union ALL . В этом случае, если первая часть возвращает какие-либо данные, вторая НИКОГДА не выполняется!