Пятница , 29 Март 2024
ДомойПубликацииmysql: выборка случайных записей из таблицы

mysql: выборка случайных записей из таблицы

php

иногда встаёт задача случайной выборки записей из таблицы базы данных. на помощь приходит, как правило, старое, но не рекомендуемое решение:

SELECT *
FROM `articles`
ORDER BY RAND()
LIMIT 3;

данный запрос возвращает 3 случайных записи из таблицы `articles`. но если записей очень много и/или выборка достаточно сложная, формирование ответа может занимать секунды. ещё один минус — запрос не может быть закеширован. вернее даже кешировать можно, но с ограничениями. допустим, в течение 10 минут пользователи будут видеть одинаковые случайные новости. однако побороть такое поведение способ есть.

для этого на первом шаге придётся выполнить 2 запроса к базе. зато после первый запрос можно закешировать навечно (точнее на время, пока не будет добавлена/удалена запись из таблицы). на следующих шагах запрос к базе останется, но выполнятся он будет максимально быстро. итак, что у нас есть: таблица статей с первичным ключём `id` (напомню: значения первичного ключа уникальны; выборка по его значениям происходит очень быстро). код для иллюстрации:

// если есть собственный механизм кеширования, лучше использовать его
// для наибольшей производительности можно использовать memcache
// файл для хранения кеша
$cache_file = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'ids.cache';
// если файл существует
if (file_exists($cache_file)) { // получить значения из него
    $ids = unserialize(file_get_contents($cache_file));
} else { // иначе, сформировать значения запросом
    // получить все `id` таблицы
    $query = SELECT `id` FROM `articles`';
    $r     = mysql_query($query);
    $ids = array();
    while ($n = mysql_fetch_row($r)) $ids[] = $n[0];
    // записать полученные идентификаторы в файл
    file_put_contents($cache_file, serialize($ids));
}
// теперь у нас есть идентификаторы всех первичных ключей
// перемешаем их
shuffle($ids);
// сделаем срез массива и получим требуемое количество (здесь 3)
$rand_ids = array_slice($ids, 0, 3);
// сформируем запрос на получение нужных статей
$query '
    SELECT *
    FROM `articles`
    WHERE `id` IN (' . implode(',', $rand_ids) . ')
    LIMIT 3';
// далее следует запрос к базе и получение записей

если записи в таблицу `articles` добавляются/удаляются, необходимо удалять файл кеша (для простоты). теперь, даже если первый запрос (для получения значений всех первичных ключей) будет достаточно долгий, это вполне компенсируется последующей скоростью выполнения. а на странице всегда будет список уникальных статей, чего, собственно, и добивались.

Рейтинг: 0

Автор публикации

2 070
не в сети 11 месяцев

x64 (aka andi)

Комментарии: 2893Публикации: 405Регистрация: 02-04-2009
Так себеНеплохоХорошоЗамечательноСупер! (Оценок пока нет)
Загрузка...

Оставить комментарий

Политика конфиденциальности

Наш сайт использует файлы cookies, чтобы улучшить работу и повысить эффективность сайта. Продолжая работу с сайтом, вы соглашаетесь с использованием нами cookies и политикой конфиденциальности.

Принять