Получение случайной строки через SQLAlchemy

Вот четыре различных варианта, от py самого медленного до самого sql-syntax быстрого. timeit результаты внизу:

from sqlalchemy.sql import func
from sqlalchemy.orm import load_only

def simple_random():
    return random.choice(model_name.query.all())

def load_only_random():
    return random.choice(model_name.query.options(load_only('id')).all())

def order_by_random():
    return model_name.query.order_by(func.random()).first()

def optimized_random():
    return model_name.query.options(load_only('id')).offset(
            func.floor(
                func.random() *
                db.session.query(func.count(model_name.id))
            )
        ).limit(1).all()

timeit результаты random-sample для 10 000 запусков на моем databases Macbook с таблицей PostgreSQL prng с 300 строками:

simple_random(): 
    90.09954111799925
load_only_random():
    65.94714171699889
order_by_random():
    23.17819356000109
optimized_random():
    19.87806927999918

Вы можете rand легко увидеть, что использование sql-select func.random() намного быстрее, чем возврат dbms всех результатов в random.choice() Python.

Кроме sql-query того, по мере увеличения sqlalchemy размера таблицы производительность sql-syntax order_by_random() будет значительно снижаться, поскольку python для ORDER BY требуется полное сканирование db таблицы, а для COUNT в optimized_random() можно database использовать индекс.

python

sql

database

random

sqlalchemy

2022-11-02T14:19:09+00:00