У меня есть таблица пользователей, идентификатор пользователя публичный. Но я хочу запутать количество
зарегистрированный пользователь и тенденции проекта, поэтому я не хочу иметь общедоступные идентификаторы.
Когда создается новый пользователь, я хочу найти случайное целое число, которое больше определенного числа и которого еще нет в базе данных.
Наивный код:
<?php
$found = false;
while(!$found) {
$uid = rand(1000000000,4294967295) // find random number betwen minimum and maximum
$dbh->beginTransaction();
// check if user id is in use, and if not insert it
if($dbh->query("SELECT * FROM users WHERE uid = $uid")) {
$dbh->exec("INSERT INTO users (uid) VALUES ($uid)");
$found = true;
}
$dbh->commit();
}
// we just got our new uid ...
?>
Это сработает, но может стать неэффективным. Правда, что есть большой диапазон и вероятность попадания неиспользованного uid высока. Но что, если я хочу использовать меньший диапазон, потому что я не хочу иметь такие длинные идентификаторы?
Пример моей заботы:
- 60% всех идентификаторов пользователей используются
- Вероятность попадания в неиспользованный UID равна 0,4
- первая попытка имеет 0,4% успеха
- , если 1-ая неудача, вторая попытка имеет вероятность 0.6 * 0.4
- так что с максимумом двух попыток у меня 0,4 + 0,6 * 0,4 вероятности (это правда ??)
Итак, один из способов оптимизации заключается в следующем:
- найти случайное число, проверить, свободно ли оно, если нет, увеличить его на 1, повторить попытку и т. Д.
- если выбрано максимальное число, продолжите с минимального числа
Это должно дать мне число с максимальным временем выполнения O (диапазон)
Звучит довольно плохо, но я думаю, что это не так, потому что я отправляю случайные числа в базу данных, и что они все в начале, очень маловероятны. Так насколько это хорошо / плохо на самом деле?
Я думаю, что это будет работать нормально, но я хочу, чтобы ЛУЧШЕ
Так что насчет этого?
- найти случайное число
- запросить в базе данных, сколько чисел занято во всем диапазоне диапазона, начиная с этого числа (этот первый шаг тривиален ...)
- если в этом диапазоне заняты числа, разделите диапазон пополам и попробуйте снова. начиная с начального номера
- если занятые числа, разделите диапазон пополам и попробуйте снова. начиная с начального номера
Если я правильно подумаю, это даст ма число с максимальным временем O (log (range)).
Это очень приятно, потому что log () довольно хорош. Однако я думаю, что этот метод часто будет настолько плохим, насколько возможно. Потому что с нашими случайными числами мы, вероятно, всегда будем попадать в числа с большими интервалами.
Так что в начале наш чисто случайный метод, вероятно, лучше.
Так что насчет такого лимита
- выберите текущее количество используемых номеров
- больше X, логарифмический диапазон приближения
- , если это не так, используйте чисто случайный метод
Что бы Х был и почему?
Итак, последний вопрос:
Это довольно легко и довольно сложно одновременно.
Я думаю, что это стандартная проблема, потому что многие системы используют случайные идентификаторы (заявки поддержки и т. Д.), Поэтому я не могу представить, что я первый, кто наткнулся на это.
Как бы вы решили это? Любой вклад оценивается!
Существует ли maby существующий класс / процедура, которую я могу использовать?
Или, может быть, некоторые функции базы данных, которые я могу использовать?
Я хотел бы сделать это в PHP / Mysql
ВАЖНОЕ РЕДАКТИРОВАНИЕ:
Я просто подумал о диапазоне / логарифмическом решении. Вроде бы полная фигня извините за мою формулировку потому что:
- что если я нажму занятый номер при запуске?
Тогда я делю свой диапазон так долго, если он только 1. И даже тогда число занято.
Так что это абсолютно то же самое, что чисто случайный метод с самого начала, только хуже ...
Я немного смущен, что придумал это, но я оставлю это, потому что я думаю, что это хороший пример чрезмерно сложного мышления!