Как да оптимизираме оператора ORDER BY RAND()?
sobes.tech AI
Отговор от AI
Оптимизирането на ORDER BY RAND() е трудно, тъй като изисква пълно извличане на данни за генериране на случайно число за всеки ред. Типичните подходи:
-
Избор на случайно идентификатор:
- Получаване на броя на редовете в таблицата.
- Генериране на случайно число от 0 до N-1 (или 1 до N).
- Избиране на ред с подходящо изместване или
OFFSET.
SELECT COUNT(*) FROM your_table; -- Предполага се, че общият брой редове = N SELECT * FROM your_table LIMIT 1 OFFSET floor(random() * N);Този метод е подходящ за избор на един или малък брой случайни редове. Не е ефективен за голям брой редове.
-
Случаен избор по диапазон
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 >= случайното_id LIMIT 1;Може да пропусне редове, ако има празни места в
id. - Намерете минималния и максималния
-
Създаване на временна таблица или използване на подзаявка с сортиране по случайно число:
- Избиране на подмножество данни или само
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е наложен върху подзаявката. - Избиране на подмножество данни или само
-
Използване на допълнително поле с случайно число:
- Добавяне на поле към таблицата за съхранение на случайно число.
- Периодично обновяване на това поле за всички редове.
- Подреждане по това поле.
-- Добавяне на поле 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;Изисква промени в схемата и фоновия процес на обновяване.
-
Алгоритъм "разбъркване" (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().