Kaip optimizuoti operatorių ORDER BY RAND()?
sobes.tech AI
Atsakymas iš AI
ORDER BY RAND() optimizavimas yra sudėtingas, nes jis reikalauja visų duomenų pasirinkimo, kad būtų sugeneruotas atsitiktinis skaičius kiekvienai eilutei. Įprasti būdai:
-
Atsitiktinio identifikatoriaus pasirinkimas:
- Gauti eilučių skaičių lentelėje.
- Sugeneruoti atsitiktinį skaičių nuo 0 iki N-1 (arba 1 iki N).
- Pasirinkti eilutę su atitinkamu poslinkiu arba
OFFSET.
SELECT COUNT(*) FROM your_table; -- Tarkime, bendras eilučių skaičius = N SELECT * FROM your_table LIMIT 1 OFFSET floor(random() * N);Šis metodas tinka vienos arba kelių atsitiktinių eilučių pasirinkimui. Nefektyvus dideliam eilučių skaičiui.
-
Atsitiktinio pasirinkimo pagal
iddiapazoną:- Rasti minimalų ir maksimalų
id. - Sugeneruoti atsitiktinį skaičių šiame diapazone.
- Pasirinkti eilutę su
id >= atsitiktinis_sknaudodamiLIMIT.
SELECT MIN(id), MAX(id) FROM your_table; -- Tarkime, gauti min_id, max_id -- Programoje sugeneruojame atsitiktinį `id` diapazone [min_id, max_id] -- Pavyzdžiui: atsitiktinis_id = min_id + floor(random() * (max_id - min_id + 1)) SELECT * FROM your_table WHERE id >= atsitiktinis_id LIMIT 1;Gali praleisti eilutes, jei yra tarpai
idreikšmėse. - Rasti minimalų ir maksimalų
-
Sukurti laikinas lentelę arba naudoti subužklausą su rūšiavimu pagal atsitiktinį skaičių:
- Pasirinkti duomenų pogrupį arba tik
idsubužklausoje. - Taikyti
ORDER BY RAND()šiai pogrupiai.
SELECT * FROM your_table AS t1 JOIN (SELECT id FROM your_table ORDER BY RAND() LIMIT 100) AS t2 ON t1.id = t2.id;Sumažina apkrovą, jei
LIMITtaikomas subužklausoje. - Pasirinkti duomenų pogrupį arba tik
-
Naudoti papildomą lauką su atsitiktiniu skaičiumi:
- Pridėti lauką į lentelę atsitiktinio skaičiaus saugojimui.
- Periodiškai atnaujinti šį lauką visoms eilutėms.
- Rūšiuoti pagal šį lauką.
-- Pridėti lauką ALTER TABLE your_table ADD random_sort_key FLOAT; -- Periodiškai atnaujinti UPDATE your_table SET random_sort_key = RAND(); -- Pasirinkti SELECT * FROM your_table ORDER BY random_sort_key LIMIT 10;Reikalauja pakeitimų schemoje ir foninio atnaujinimo procese.
-
"Maišymo" algoritmas (Fisher-Yates) už duomenų bazės ribų:
- Pasirinkti visus
id(arba visus duomenis, jei jie maži). - Maišyti sąrašą programoje.
- Pasirinkti pirmuosius N elementus.
// Tarkime, kad ids yra []int // ids = ... // Gauti ids iš duomenų bazės rand.Shuffle(len(ids), func(i, j int) { ids[i], ids[j] = ids[j], ids[i] }) // Dabar pirmieji N elementai ids yra atsitiktiniai // Juos galima naudoti pilnų eilučių pasirinkimui // SELECT * FROM your_table WHERE id IN (...)Tinka tik mažų eilučių skaičiaus lentelėms.
- Pasirinkti visus
Pasirinkti geriausią metodą priklauso nuo lentelės dydžio, reikalaujamo atsitiktinių eilučių skaičiaus ir konkrečios duomenų bazės valdymo sistemos. Daugeliu atvejų, kai reikia pasirinkti nedidelį kiekį atsitiktinių eilučių iš didelės lentelės, kombinacija id gavimo su vėlesniu OFFSET arba WHERE id IN (...) bus efektyvesnė nei grynas ORDER BY RAND().