Програмування → Вибір випадкових записів в MySQL

Випадковість

На перший погляд тривіальне завдання, і вирішується так само тривіально. Та насправді не все так просто, й ідеального рішення досі не існує.

Наприклад, завдання:

вибрати з таблиці myTable 15 випадкових записів.

Перше що спадає на думку це:

SELECT * FROM myTable ORDER BY RAND() LIMIT 15

Цей метод точно працює, більше того, в багатьох випадках (зокрема, коли в таблиці не багато записів) його й потрібно юзати. Основний його недолік стає зрозумілий, коли розібратися як MySQL опрацює цей запит. В процесі виконання буде створено тимчасову таблицю, в яку переносяться всі записи нашої myTable, плюс ще одне поле з результатами роботи RAND(). Потім записи по ньому сортуються і відбирається 15 штук.

Інший метод, годиться коли існує числовий PRIMARY KEY без випадів (випади утворюються при видаленні записів):

  • Вибираємо максимальне значення id (MAX_ID)
  • Генеруємо випадкові числа від 1 до MAX_ID (15 штук)
SELECT * FROM myTable WHERE id IN ($rand1,$rand2,... ...,$rand15);

Виконується практично миттєво, та навряд чи десь таке вдасться заюзати, ібо таблиці з послідовним індексом рідко зустрінеш.

Далі приводжу різні методи вибору з часом виконання та примітками. Час замірявся на моєму компі як середній за декілька запитів. Таблиця на 500 000 рядків.

Варіант 1

SELECT * FROM myTable ORDER BY RAND() LIMIT 15

0,63 сек. Перший спосіб, для порівняння.

Варіант 2

SELECT * FROM myTable WHERE RAND()<0.001 ORDER BY RAND() LIMIT 15;

0,21 сек. Цікавий варіант, хоча тратимо час на обчислення і порівняння лишніх RAND омів, зате зменшуємо розмір таблиці, що сортуватиметься в пам’яті.

Варіант 3

Обчислюємо 15 випадкових значень від 0 до кількості записів в таблиці, і робимо 15 запитів через UNION:

(SELECT id FROM myTable LIMIT $rend1, 1) UNION (SELECT id FROM myTable LIMIT $rend2, 1) UNION ... ... (SELECT id FROM myTable LIMIT $rend15, 1);

1,54 сек. Трохи божевільний варіант, приводжу його так як одним автором він позиціонувався як самий правильний.

Варіант 4

Створюємо додаткову таблицю з двох полів, перше — id з нашої таблиці, друге — випадковий номер без дир. Ведення таблиці повісити на трігери. Вибірка проводитиметься швидко, але якщо в таблицю часто добавляються / видаляються записи — буде біда.

Знову повторюсь, не існує ідеального рішення, тому якщо вам потрібно вибирати випадкові записи з БД — серйозно задумайтесь, чи це реально потрібно, і чи справді вони повинні бути повністю випадкові.

Теги: ,
21.07.2009 16:44 Автор: Strange_V Хіти: 373

Напишіть відгук