2015-09-04 5 views
3

У меня есть три таблицы: пользователей с уникальным nickname, более четырехсот Имен, 300000 плюс прилагательных и тонны возможных комбинаций.Создание большого числа уникальных случайных комбинаций

При подписке пользователь может создать уникальный, случайный и, надеюсь, смешной ник, объединив случайное имя со случайным прилагательным. Пользователь нажимает кнопку и Voilà! рождается волнующая личность.

Я выбираю случайные имена и прилагательные, выполнив два запроса для каждого:

SELECT FLOOR(RAND() * COUNT(*)) AS `offset` FROM names/adjectives 

и

SELECT * FROM names/adjectives LIMIT offset, 1 

Затем я проверяю, если пользователь был достаточно неудачен, чтобы сформировать уже существующую личность.

SELECT COUNT(nickname) FROM users WHERE nickname=:generatedNickname 

Если бы он был, бедный человек, я прокручивал его снова, пока он не оседает над чем-то незанятым.

Но, как вы, наверное, уже выяснили, рост базы пользователей также означает более длинные петли и больше пота из моего слабого EC2 Tier 1 Matchbox. Итак, я придумал блестящее решение: Что делать, если я предварительно создаю все возможные комбинации и набиваю их в огромную таблицу? Это позволит простую операцию по разрыву и воспроизведению, пока я буду потягивать волнующие мартини на каком-то анонимном пляже, или я? Будет ли мой скромный экземпляр LAMP дрожать и убегать при славном взгляде на огромные столы (как мужчины, так и женщины)? Есть ли лучшее решение?

+0

Будете ли вы хранить комбинации по текстовому значению или как два внешних ключа для этих таблиц? 300K * 400 = около 120 миллионов комбинаций. Это не маленькая таблица, но если она содержит только два ints, тогда она управляема (скажем, где-то около пары гигабитов), - но вы действительно ожидаете, что так много пользователей, что среднее ожидаемое количество циклов когда-либо будет превышать 2? (это будет означать, что у некоторых пользователей 60M, если моя математика не слишком ржавая) – jkavalik

+0

Но если вы все еще боитесь этого, тогда вы можете предварительно размножать тысячи комбинаций «в автономном режиме» (в ночное время) в такую ​​таблицу, когда она становится «слишком пустой» "и использовать их, не нужно генерировать их все сразу. – jkavalik

+0

@jkavalik Комбинации хранятся в виде текста. Нет, у меня никогда не будет такого количества пользователей. Идея о том, что вероятность столкновения невелика, тоже перешла мне на ум, но никогда не больно спрашивать людей, которые более опытные. Спасибо чувак! –

ответ

1

Создание этих комбинаций заранее приведет к огромному количеству данных. Я это не рекомендую. Мое предложение было бы использовать лучший источник случайности, чем RAND(). Вероятность столкновения (основанная на ваших оценках) составляет всего около n/120000000, где n - это количество пользователей, поэтому ваш цикл не будет работать очень долго, если вы сделать получить его.

+0

Вы только что подтвердили мою мысль о возможности столкновения, но, как я уже сказал @jkavalik, никогда не боится спрашивать. Не могли бы вы предложить лучший источник случайности, лучше ли php 'rand'? –

+1

@ Răzvan: PHP-rand() 'на самом деле не выше. Если вы можете, используйте что-то вроде ['openssl_random_pseudo_bytes()'] (http://php.net/openssl_random_pseudo_bytes), ['random_bytes()'] (http://php.net/random_bytes) или ['random_int () '] (http://php.net/random_int). Случайность, которая криптографически безопасна, - ваш лучший выбор для минимизации столкновений. – jwueller

1
  1. Дайте существительных и прилагательных в AUTO_INCREMENT идентификатор, который является PRIMARY KEY. Другой столбец (существительные/прилагательные) должен быть UNIQUE.

  2. Держите COUNT(*) для каждой из этих двух таблиц где-то удобно. Повторите эти подсчеты, если вы когда-либо изменяете таблицы. Не делайте SELECT COUNT(*) в приведенном ниже коде, он будет выполнять сканирование таблицы - не дешево.

  3. Используйте SELECT noun FROM Nouns WHERE id = CEIL(noun_count * RAND()), чтобы получить случайное «существительное». То же самое для «прилагательного».

  4. Теперь нам нужно проверить наличие дубликатов. Вы сохранили компиляцию прилагательного-существительное в пользовательской таблице, правильно? и это INDEXed, правильно? Поэтому просто проверьте этот комбо, который уже использовался.

  5. Если это дубликат, то начните сначала.

Ни один из шагов не займет много времени, поэтому даже если вы должны (редко) повторить процесс, это не займет много времени.

PS: Я думаю, вы обнаружите, что RAND() достаточно хорошо для этой задачи.

Смежные вопросы