2008-09-19 7 views
5

Привет, мне нужно сгенерировать 9 цифр уникальных номеров учетных записей. Вот мой псевдокод:Создание уникальных номеров учетных записей - рекурсивный вызов

function generateAccNo() 

    generate an account number between 100,000,000 and 999,999,999 

    if the account number already exists in the DB 
     call generateAccNo() /* recursive call */ 
    else 
     return new accout number 
    end if 

end function 

функция, кажется, работает хорошо, но я немного беспокоюсь о рекурсивном вызове.

Будет ли это причиной утечки памяти (PHP 5 под apache)?

Является ли это приемлемым способом решения этой проблемы?

Спасибо за ваш вклад.

ответ

8

Вы понимаете, что это может привести к переполнению стека, верно? По мере увеличения количества customesr вероятность не найти приемлемого номера учетной записи увеличивается.

Кроме того, почему вы не можете просто делать последовательные номера счетов и просто увеличиваться на единицу каждый раз? При таком подходе вам просто нужно будет прочитать max id в настоящее время в базе данных и просто увеличить его.

Извините, что так грубо, но ваше решение - ужасный способ решить эту проблему. Он будет использовать тонны памяти (так как стеки могут расти бесконечно), и это вызовет массу дорогостоящих вызовов в базу данных.

Вы действительно должны рассмотреть несколько иного подход:
Я настоятельно рекомендую просто увеличивающееся количество клиентов каждый раз, когда вы создаете клиент. Фактически, если вы правильно настроили свой db (с автоматическим увеличением в столбце id), вам даже не нужно будет устанавливать идентификатор. Идентификатор будет установлен для вас, когда вы вставляете нового клиента.

+2

, но stackoverflow - это потрясающе! – Aaron 2008-09-19 01:02:13

+0

Это было бы маловероятно. Это зависит от случайности сгенерированного номера счета и количества активных учетных записей. С управляемым кодом вы должны откладывать 10 тысяч раз, чтобы сломать стек. Когда вероятность неединственности приближается к 10 000: 1, тогда пришло время волноваться. – Wedge 2008-09-19 01:11:44

+0

Спасибо Esetban, что вы сказали мне какое-то чувство, hehe :) Я позволю БД создать для меня значение и придерживаться последовательных чисел. Спасибо – 2008-09-19 01:18:14

0

Здесь нет необходимости использовать рекурсию. Простой цикл будет таким же быстрым и потребляет меньше пространства стека.

0

Вы можете поместить его в время цикла:

function generateAccNo() 

    while (true) {  

     generate an account number between 100,000,000 and 999,999,999 

     if the account number already exists in the DB 
      /* do nothing */ 
     else 
      return new accout number 
     end if 
    } 

end function 
1

Кажется, хорошо, но я думаю, что вам нужно какое-то фильеры состояния, сколько раз вы собираетесь позволить этому бежать, прежде чем отказаться?

Я знаю, что это кажется маловероятным с огромным диапазоном номеров, но что-то может пойти не так, как будто вы вернетесь к предыдущему вызову, который снова вызовет себя, ad-nauseum.

2

Здесь нет необходимости использовать рекурсивный вызов. Запустите простой цикл while в функции тестирования против небытия в качестве условного, например.

function generateAccNo() 

    generate an account number between 100,000,000 and 999,999,999 

    while (the account number already exists in the DB) { 
     generate new account number; 
    } 
    return new account number 

end function 

Случайного генерируя-и-тестирование является неоптимальным подходом к созданию уникальных номеров счетов, хотя, если этот код для чего-нибудь другого, чем игрушка.

+1

WHAT!?! Вы хотите сделать, возможно, 899 999 999 дБ хитов только для создания номера учетной записи? Похоже на плохой подход ко мне. – 2008-09-19 01:06:57

0

Почему нет:

lock_db 
do 
    account_num <= generate number 
while account_num in db 

put row with account_num in db 

unlock_db 
0

Почему нет базы данных справиться с этим? В SQL Server вы можете просто иметь столбец идентификаторов, который начинается с 100000000. Или вы можете использовать sql в любом db, который у вас есть. Просто получите максимальный id плюс 1.

1

Создание номеров учетных записей последовательно - это риск для безопасности - вы должны найти другой алгоритм для этого.

1

В качестве альтернативы вы можете вести отдельную таблицу, содержащую буфер сгенерированных, известных как уникальные номера учетных записей. Эта таблица должна иметь идентификатор целочисленного значения с автоматическим увеличением. Когда вам нужен номер учетной записи, просто потяните запись с самым низким индексом в буфере и удалите ее из этой таблицы. Имейте некоторый процесс, который работает регулярно, который пополняет буфер и гарантирует, что он имеет емкость >> нормального использования. Преимущество заключается в том, что время, затрачиваемое конечным пользователем на создание номера учетной записи, будет по существу постоянным.

Кроме того, я должен отметить, что накладные расходы на обработку или риски рекурсии или итерации, реальной проблемой является детерминизм и накладные расходы на повторение запросов к базе данных. Мне нравится решение случайного + последовательного решения TheZenker. Гарантируется создание уникального идентификатора без добавления лишних накладных расходов.

3

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

. GUID

Если действительно уникальный идентификатор требуется с минимальными усилиями, рассмотрите GUID, ваша БД, скорее всего, сможет назначить для вас при вставке, если не создать его в коде. Он гарантированно будет уникальным, хотя он не очень удобен для пользователя. Однако в сочетании с последовательным AccountRecordId, сгенерированным БД на вставке, вы должны иметь сплошную комбинацию

. Композитный ключ: случайный + последовательный

Один из способов удовлетворения всех потребностей, хотя на поверхности он чувствует себя немного глупым, заключается в создании составного номера счета из последовательной клавиши db из 5 цифр (или более), а затем другой 5 цифр случайности. Если бы случайное число было дублировано, это не имело бы значения, поскольку последовательный идентификатор гарантировал бы уникальность всего номера счета

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

  • Нет связанных вопросов^_^