Sobes.tech
Middle+

Kako optimizovati operator ORDER BY RAND()?

sobes.tech АИ

Одговор од АИ

Оптимизација ORDER BY RAND() је тешка, јер захтева потпуно преузимање података за генерисање случајног броја за сваки ред. Типични приступи:

  1. Избор случајног идентификатора:

    • Добити број редова у таблици.
    • Генерисати случајни број од 0 до N-1 (или 1 до N).
    • Изабрати ред са одговарајућим помером или OFFSET.
    SELECT COUNT(*) FROM your_table;
    -- Предпоставља се да је укупни број редова = N
    
    SELECT * FROM your_table LIMIT 1 OFFSET floor(random() * N);
    

    Ова метода је погодна за избор једног или малог броја случајних редова. Неефикасна је за велики број редова.

  2. Случајни избор по опсегу id:

    • Пронаћи минимални и максимални id.
    • Генерисати случајни број у том опсегу.
    • Изабрати ред са id >= случајни_број користећи LIMIT.
    SELECT MIN(id), MAX(id) FROM your_table;
    -- Предпоставља се да су добијени min_id, max_id
    
    -- У апликацији генеришемо случајни id у опсегу [min_id, max_id]
    -- На пример: случајни_id = min_id + floor(random() * (max_id - min_id + 1))
    
    SELECT * FROM your_table WHERE id >= случајни_ид LIMIT 1;
    

    Може пропустити редове ако постоје празни простори у id.

  3. Креирање привремене табеле или коришћење подзадатка са сортирањем по случајном броју:

    • Изабрати подскуп података или само id у подзадатку.
    • Примени ORDER BY RAND() на овај подскуп.
    SELECT *
    FROM your_table AS t1 JOIN (SELECT id FROM your_table ORDER BY RAND() LIMIT 100) AS t2
    ON t1.id = t2.id;
    

    Смањује оптерећење ако је LIMIT наметнут на подзадатку.

  4. Користење додатног поља са случајним бројем:

    • Додати поље у табелу за чување случајног броја.
    • Периодично ажурирати ово поље за све редове.
    • Сортирати по овом пољу.
    -- Додавање поља
    ALTER TABLE your_table ADD random_sort_key FLOAT;
    
    -- Периодично ажурирање
    UPDATE your_table SET random_sort_key = RAND();
    
    -- Избор
    SELECT * FROM your_table ORDER BY random_sort_key LIMIT 10;
    

    Захтева измене у шеми и позадински процес ажурирања.

  5. Алгоритам "мешања" (Fisher-Yates) ван базе података:

    • Изабрати сва id (или све податке ако су мали).
    • Мешати листу у апликацији.
    • Изабрати првих N елемената.
    // Предпоставља се да је ids []int
    // ids = ... // Добијање ids из базе података
    
    rand.Shuffle(len(ids), func(i, j int) {
        ids[i], ids[j] = ids[j], ids[i]
    })
    
    // Сада су првих N елемената ids случајни
    // Могу се користити за избор пуних редова
    // SELECT * FROM your_table WHERE id IN (...)
    

    Погодно само за табеле са малим бројем редова.

Избор најбоље методе зависи од величине табеле, захтеваног броја случајних редова и конкретног система управљања базама података. За већину случајева, када је потребно изабрати мали број случајних редова из велике табеле, комбинација добијања id са накнадним OFFSET или WHERE id IN (...) ће бити ефикаснија од чистог ORDER BY RAND().