Опять же, создаю данный топик больше для обсуждения и информации
Имеем большую БД форума - около 1,7 млн мессаг (posts), 2,5 млн ЛС (privmsgs), 50 тыс. топиков (topics).
Действующих пользователей приходится удалять редко, однако, со временем накапливается некоторое количество неактивированных пользователей и хотелось бы их время от времени удалять (обычно это боты или пользователи, которые не подтверждают email, или отправленные в ручной аппрув и не прошедшие его юзеры)
Описываемая проблемка затрагивает как активированных пользоваталей, так и новых, неактивированных
Суть в чем:
По ходу процесса удаления пользователя натыкаемся на несколько запросов:
Код: Выделить всё
// Change user_id to anonymous for posts edited by this user
$sql = 'UPDATE ' . POSTS_TABLE . '
SET post_edit_user = ' . ANONYMOUS . '
WHERE ' . $db->sql_in_set('post_edit_user', $user_ids);
$db->sql_query($sql);
// Change user_id to anonymous for pms edited by this user
$sql = 'UPDATE ' . PRIVMSGS_TABLE . '
SET message_edit_user = ' . ANONYMOUS . '
WHERE ' . $db->sql_in_set('message_edit_user', $user_ids);
$db->sql_query($sql);
// Change user_id to anonymous for posts deleted by this user
$sql = 'UPDATE ' . POSTS_TABLE . '
SET post_delete_user = ' . ANONYMOUS . '
WHERE ' . $db->sql_in_set('post_delete_user', $user_ids);
$db->sql_query($sql);
// Change user_id to anonymous for topics deleted by this user
$sql = 'UPDATE ' . TOPICS_TABLE . '
SET topic_delete_user = ' . ANONYMOUS . '
WHERE ' . $db->sql_in_set('topic_delete_user', $user_ids);
$db->sql_query($sql);
POSTS_TABLE.post_edit_user
PRIVMSGS_TABLE.message_edit_user
POSTS_TABLE.post_delete_user
TOPICS_TABLE.topic_delete_user
Учитывая, что индексов на этих полях нет, а таблицы немаленькие, выборка идет тяжело (при том, что в случае с новыми неактивированными пользователями обновлять там нечего). Исключение разве что с таблицей topics, где немного записей.
Например, для таблицы posts - это около 4 секунд, для privmsgs - около 5,5-6 сек.
В итоге, учитывая все остальные запросы, время удаления единичного пользователя достигает 15-20 секунуд. Если это пачка пользователей - можно идти заваривать кофе, но с большой вероятностью скрипт упрется в PHPшный max_execution_time, которое обычно выставлено в районе 30 сек (в крайнем случае 60).
Вполне возможно, что стоит добавить индексы по этим полям и все бы залетало. Но тут вопрос такой, что, как я понимаю, сам индекс и его обслуживание тоже требует каких-от ресурсов, которые будут влиять на производительность, скажем, при отправке нового поста. А удаляются пользователи не шибко часто... В общем, это, конечно, вопрос к тем, кто хорошо знаком с БД.
Я пока делаю как — написал небольшое "расширение", которое по сути просто сожержит migration добавляющий этот индекс при активации, и удаляющий при отключении расширения. Ну а после активации можно быстренько удалить пользователей в любых объемах.
Ну или просто добавить/удалить индексы руками (добавление индексов по всем вышеописанным полям занимает минуты полторы-две). Ну а при индексах удаление сотни неактивированных пользователей занимает секнуд 10 - да, наверняка есть еще, что оптимизировать, но жить можно.
И последнее, что хотел бы сказать: если мы удаляем пользователя, но оставляем его мессаги - они остаются как бы от его имени (POSTS_TABLE.post_username) Но само это имя становится доступным для регистрации (что логично - пользователь то удален)... Т.е. как бы малость странновато получается. Пока не думал, как это решить.