Избирането на произволни редове винаги е трудно и няма идеални решения, които да не включват някакъв компромис. Или компрометирайте производителността, или компрометирайте дори произволното разпределение, или правете компромис с възможността за избор на дубликати и т.н.
Както @JakeGould споменава, всяко решение с ORDER BY RAND()
не мащабира добре. Тъй като броят на редовете във вашата таблица става по-голям, цената за сортиране на цялата таблица във файлов сортиране става все по-лоша и по-лоша. Джейк е прав, че заявката не може да бъде кеширана, когато сортирането е произволно. Но това не ме интересува толкова, защото така или иначе обикновено деактивирам кеша на заявките (той има свои собствени проблеми с мащабируемостта).
Ето решение за предварително рандомизиране на редовете в таблицата чрез създаване на колона с номер на редове и присвояване на уникални последователни стойности:
ALTER TABLE products ADD COLUMN rownum INT UNSIGNED, ADD KEY (rownum);
SET @rownum := 0;
UPDATE products SET rownum = (@rownum:[email protected]+1) ORDER BY RAND();
Сега можете да получите произволен ред чрез търсене в индекс, без сортиране:
SELECT * FROM products WHERE rownum = 1;
Или можете да получите следващия произволен ред:
SELECT * FROM products WHERE rownum = 2;
Или можете да получите 10 произволни реда наведнъж или друго число, което искате, без дубликати:
SELECT * FROM products WHERE rownum BETWEEN 11 and 20;
Можете да пренастроите на случаен принцип по всяко време:
SET @rownum := 0;
UPDATE products SET rownum = (@rownum:[email protected]+1) ORDER BY RAND();
Все още е скъпо да направите произволното сортиране, но сега не е нужно да го правите при всяка заявка SELECT. Можете да го правите по график, надяваме се в непиковите часове.