mrBingo Опубликовано 29 октября, 2012 Жалоба Поделиться Опубликовано 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? Ссылка на комментарий Поделиться на другие сайты Поделиться
Ego Drama Опубликовано 29 октября, 2012 Жалоба Поделиться Опубликовано 29 октября, 2012 (изменено) Жестяное, жуткое решение. Очевидно, что РБД совершенно не подходит к проблеме (по крайней мере, если нет специальных средств [может в Oracle что есть?]). Не занимайтесь ерундой, возьмите подходящий инструмент. На вскидку, могу предложить Redis. Смотреть следует в сторону spop, srandmember, randomkey. Все эти команды с O(1). Изменено 29 октября, 2012 пользователем Ego Drama Ссылка на комментарий Поделиться на другие сайты Поделиться
mrBingo Опубликовано 30 октября, 2012 Автор Жалоба Поделиться Опубликовано 30 октября, 2012 Если задача поставлена сделать в MySQL значит будем делать в MySQL это не обсуждается, ибо я не первый раз работаю с данным заказчиком, менять хостера он не будет однозначно. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Для публикации сообщений создайте учётную запись или авторизуйтесь
Вы должны быть пользователем, чтобы оставить комментарий
Создать учетную запись
Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!
Регистрация нового пользователяВойти
Уже есть аккаунт? Войти в систему.
Войти