質問
こんにちは、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
関数はうまく機能しているようですが、再帰呼び出しが少し心配です。
これによりメモリ リークが発生しますか (Apache 上の PHP 5)。
これはこの問題に対処する許容可能な方法ですか?
ご意見ありがとうございます。
解決
これによりスタック オーバーフローが発生する可能性が非常に高いことがわかりますよね?顧客の数が増えると、受け入れ可能な口座番号が見つからない可能性が高くなります。
また、なぜ口座番号を連続して毎回 1 ずつ増やすことができないのでしょうか?このアプローチでは、現在データベースにある最大 ID を読み取り、それをインクリメントするだけで済みます。
率直に言って申し訳ありませんが、あなたの解決策は問題に取り組むにはひどい方法です。大量のメモリを使用し (スタックが無限に増大する可能性があるため)、データベースに対して大量の高価な呼び出しを行うことになります。
他のアプローチを実際に検討する必要があります。
顧客を作成するたびに顧客番号を増やすことを強くお勧めします。実際、データベースを適切に設定していれば (ID 列の自動インクリメントを使用して)、ID を設定する必要さえありません。新しい顧客を挿入するたびに ID が設定されます。
他のヒント
私はそれが再帰と再帰の関係になるとは本当に思いません。どちらも、データセットが大きくなるにつれて、また乱数生成が正しく実装されていない場合に問題が発生する傾向があります。2 つのアイデアが思い浮かびます。
. 。GUID
できる限り少ない労力で真に一意の ID が必要な場合は、GUID を検討してください。コードで作成しなくても、DB は挿入時に割り当てることができる可能性が高くなります。あまりユーザーフレンドリーではありませんが、ユニークであることが保証されています。ただし、挿入時に DB によって生成される連続した AccountRecordId と組み合わせると、確実な組み合わせが得られます。
. 。複合キー:ランダム + シーケンシャル
すべてのニーズに対応する 1 つの方法は、表面的には少し面倒に感じますが、5 桁 (またはそれ以上) の連続した db キーと、さらに 5 桁のランダムな数字から複合アカウント番号を作成することです。乱数が重複した場合でも、連続 ID によってアカウント番号全体の一意性が保証されるため、問題にはなりません。
ここで再帰呼び出しを使用する必要はありません。条件として存在しないことをテストする関数で単純な 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
ただし、このコードがおもちゃ以外のものである場合、ランダムに生成してテストすることは、一意のアカウント番号を生成するための次善のアプローチです。
問題ないようですが、何らかの死亡条件が必要だと思います。諦めるまでに何回実行するつもりですか?
膨大な数の電話番号を考えるとこのようなことは起こりそうにないとは思いますが、何か問題が発生して前の通話に戻り、再び自分自身を「吐き気がする」と呼ぶ可能性があります。
アカウント番号を順番に生成することはセキュリティ上のリスクです。それを行うための他のアルゴリズムを見つける必要があります。
あるいは、生成された一意の口座番号のバッファを含む別のテーブルを管理することもできます。このテーブルには、自動インクリメントされる整数 ID が必要です。口座番号が必要な場合は、バッファ内のインデックスが最も小さいレコードを取得し、そのテーブルから削除するだけです。バッファを補充し、バッファの容量が通常の使用量を超えていることを確認する、定期的に実行されるプロセスを用意します。利点は、エンド ユーザーがアカウント番号の作成に費やす時間が基本的に一定であることです。
また、処理のオーバーヘッドや再帰や反復のリスク、実際の問題は決定論とデータベース クエリを繰り返すオーバーヘッドであることに注意する必要があります。私は TheZenker のランダム + シーケンシャルのソリューションが好きです。不必要なオーバーヘッドを追加することなく、一意の ID を生成することが保証されます。
ここでは再帰を使用する必要はありません。単純なループは同じくらい高速で、消費するスタック領域も少なくなります。
これを while ループに入れることができます。
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
なぜだめですか:
lock_db
do
account_num <= generate number
while account_num in db
put row with account_num in db
unlock_db
なぜデータベースにこれを処理させないのでしょうか?SQL Server では、100000000 で始まる ID 列だけを持つことができます。または、お持ちのデータベースで SQL を使用することもできます。最大 ID に 1 を加えた値を取得するだけです。