Страница 1 из 1

Удаление пользователей, нюансы с user_delete()

Добавлено: 06.11.2019 1:43
Andex
Итак, продолжим
Опять же, создаю данный топик больше для обсуждения и информации

Имеем большую БД форума - около 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) Но само это имя становится доступным для регистрации (что логично - пользователь то удален)... Т.е. как бы малость странновато получается. Пока не думал, как это решить.

Re: Удаление пользователей, нюансы с user_delete()

Добавлено: 06.11.2019 5:31
rxu
Andex писал(а): 06.11.2019 1:43 Вполне возможно, что стоит добавить индексы по этим полям и все бы залетало.
Скорее всего. Думаю, ресурсов на их обслуживание уходит не много.
Плюс там есть два апдейта одной и той же таблицы постов. которые, видимо, можно как-то объединить в один.
Andex писал(а): 06.11.2019 1:43 если мы удаляем пользователя, но оставляем его мессаги - они остаются как бы от его имени (POSTS_TABLE.post_username) Но само это имя становится доступным для регистрации
Они становятся гостевыми, такими, как если бы гость при постинге указал такое имя.

Re: Удаление пользователей, нюансы с user_delete()

Добавлено: 06.11.2019 12:33
Andex
rxu писал(а): 06.11.2019 5:31 Скорее всего. Думаю, ресурсов на их обслуживание уходит не много.
Тут палка о двух концах...
С одной стороны, можно прилепить индексы и забыть. С другой стороны — выборка по этим полям крайне редкая, нашел селект по этим полям только в одном месте viewtopic (и то не совсем понял, для чего там эта выборка)
А индекс будет обновляться при каждом добавлении нового поста (сама операция и так ресурсоемкая)... В общем, не знаю как лучше, т.к. добавление поста, имхо, должно быть максимально быстрым, чтобы из-за удаления каких-то там пользователей не страдали нормальные юзеры...

Кстати, еще об индексах: как-то раньше писал про похожую историю в notifications. Собственно, там был добавлен индекс, вроде все шуршит нормально уже не первый год (правда, еще написано расширение, которое по прошествии периода чистит _непрочитанные_ уведомления, т.к. некоторые пользователи тупо не пользуются данной функчиональностью и соответствующая табличка тоже растет космически)
rxu писал(а): 06.11.2019 5:31 Они становятся гостевыми, такими, как если бы гость при постинге указал такое имя
Да, я понимаю
Но в моем частном случае это выглядит не ок. Т.к. гости не имеют прав постить (и мне кажется глобально такая ситуация значительно преобладает), а создать новый акк с таким же именем получается можно... И потом попробуй разберись (с точки зрения обычного юзера) чьи на самом деле эти мессаги...
Тут можно при реге делать, например, DISTINCT SELECT по POSTS_TABLE.post_username... но опять же, индекса там нет, выборка - в пол секунды у меня, добавлять индекс - такая се затея... Или может я просто зря боюсь лишних индексов?

Re: Удаление пользователей, нюансы с user_delete()

Добавлено: 06.11.2019 13:45
Nekstati
Andex писал(а): 06.11.2019 12:33 И потом попробуй разберись (с точки зрения обычного юзера) чьи на самом деле эти мессаги...
Создать звание "Гость", назначить его группе "Гости", и под никами удалённых юзеров будет отображаться это звание. Можно назначить и аватару.

Re: Удаление пользователей, нюансы с user_delete()

Добавлено: 06.11.2019 14:02
Andex
Nekstati, как вариант!

Единственное, что мне не нравится в этой схеме:
Кто-то был забанен. Чтобы не хранить в БД всякий хлам, вроде ЛСок забанненого и прочую инфу, через какое-то время этот пользователь удаляется вовсе (но посты его остаются, т.к., например, являются частью диалотгов на форуме и выпилить их - нарушить последовательность диалогов и все такое). И тут приходит этот забанненый юзер и регается под тем же самым акком. Такое себе обнуление аккаунта вместо бана получается.

Re: Удаление пользователей, нюансы с user_delete()

Добавлено: 06.11.2019 14:04
Sheer
Andex писал(а): 06.11.2019 1:43 написал небольшое "расширение
Ну так добавьте в расширение блокировку ника при удалении пользователя. Имя пользователя будет добавлено в "черный список", и уже никто не сможет зарегистрироваться под этим именем.

Re: Удаление пользователей, нюансы с user_delete()

Добавлено: 06.11.2019 14:17
Andex
Sheer, Тоже вариант
Надо посмотреть как устроена проверка имен в ЧС при регистрации, а то список может оказаться немаленьким)
Тут вопрос именно в блокировании имен удаленных, но ранее активированных пользователей, а неактивированных можно сносить как угодно.
Спасибо, наверно покопаю именно в этом направлении.