Jump to content
СофтФорум - всё о компьютерах и не только

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


mrBingo
 Share

Recommended Posts

Задача:

Есть таблица 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?

Link to comment
Share on other sites

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

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

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

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

Edited by Ego Drama
Link to comment
Share on other sites

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

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...