Перейти к содержанию
СофтФорум - всё о компьютерах и не только

Выбор случайных записей MySQL


mrBingo

Рекомендуемые сообщения

Задача:

Есть таблица MySQL из 3х полей int (id записи, auto_inc), varchar(200), varchar(15) содержащая примерно 50 тысяч записей, со временем возможно будет больше. Есть веб-приложение на php, которому каждые 40 секунд нужна новая случайная запись из этой таблицы, притом выбираемые записи должны повторяться не чаще чем раз в час. Все пользователи приложения подключенные одновременно используют одну и ту же запись. Нагрузка на сервер должна быть минимальной.

Идеи решения:

Так как все пользователи работают с данными одной и той же записи, думаю будет оптимальнее выбирать записи из таблицы крон скриптом и переносить их во временную таблицу. Также оптимальнее будет выбирать сразу по 45 записей раз в 30 минут, чем 1 запись раз в 40 секунд (поправьте, если я не прав).

Сразу возникает вопрос: что оптимальние, переносить записи целиком во временную таблицу, или же переносить только их id, а потом выбирать их посредством INNER JOIN запроса из основной таблицы?

ORDER BY RAND() одназначно для такой большой таблицы не подходит, даже учитывая, что такой запрос делается ровно 1 раз в 30 минут, тем более он не обеспечит неповторяемость с предыдущей пачкой в 45 записей, которая необходима из условия задачи (за час выбираются 90 записей, а любые 90 выбраных подряд записей должны быть уникальны).

Пока идея такая:

Пусть исходная таблица называется t_src и содержит поля: id, s1, s2

Временная таблица называется t_temp и содержит поля: id, src_id, s1, s2, for_del где поле for_del - это информация для удаления отработавших записей, хранит время переноса, естественно индекс

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

SELECT COUNT(id) FROM t_src;

2 запрос получает src_id последних 45 записей из временной таблицы:

SELECT src_id FROM t_temp ORDER BY id DESC LIMIT 45;

Далее php генерирует 45 случайных индексов на основе данных полученых из этих двух запросов

3 запрос переносит записи:

INSERT INTO t_temp (src_id, s1, s2, for_del) SELECT id, s1, s2, NOW() FROM t_src WHERE id IN ( тут список из 45 сгенерированых php индексов );

4 запрос удаляет записи из временной таблицы, которые уже не нужны:

DELETE FROM t_temp WHERE for_del < NOW() - INTERVAL 1 HOUR;

Есть несколько вопросов:

1) В моем примере в 3 запросе вызов функции NOW() происходит 45 раз. Будет ли оптимальнее использовать в поле for_del число вместо времени? Если да, то как это реализовать?

2) Возможно ли здесь сократить число запросов, чтобы снизить нагрузку на сервер?

3) Есть идея обрывать работу данного скрипта при отсутствии активности приложения более получаса, дабы снизить нагрузку. Как гарантировать, что у приложения всегда будут записи в t_temp?

Ссылка на комментарий
Поделиться на другие сайты

Жестяное, жуткое решение.

Очевидно, что РБД совершенно не подходит к проблеме (по крайней мере, если нет специальных средств [может в Oracle что есть?]).

Не занимайтесь ерундой, возьмите подходящий инструмент.

На вскидку, могу предложить Redis. Смотреть следует в сторону spop, srandmember, randomkey. Все эти команды с O(1).

Изменено пользователем Ego Drama
Ссылка на комментарий
Поделиться на другие сайты

Если задача поставлена сделать в MySQL значит будем делать в MySQL это не обсуждается, ибо я не первый раз работаю с данным заказчиком, менять хостера он не будет однозначно.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...