mrBingo Posted October 29, 2012 Report Share Posted October 29, 2012 Задача: Есть таблица 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 More sharing options...
Ego Drama Posted October 29, 2012 Report Share Posted October 29, 2012 (edited) Жестяное, жуткое решение. Очевидно, что РБД совершенно не подходит к проблеме (по крайней мере, если нет специальных средств [может в Oracle что есть?]). Не занимайтесь ерундой, возьмите подходящий инструмент. На вскидку, могу предложить Redis. Смотреть следует в сторону spop, srandmember, randomkey. Все эти команды с O(1). Edited October 29, 2012 by Ego Drama Link to comment Share on other sites More sharing options...
mrBingo Posted October 30, 2012 Author Report Share Posted October 30, 2012 Если задача поставлена сделать в MySQL значит будем делать в MySQL это не обсуждается, ибо я не первый раз работаю с данным заказчиком, менять хостера он не будет однозначно. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now