ユーザーフレンドリーな英数字ID(ビジネスID、SKUなど)を生成するためのオプションは何ですか

StackOverflow https://stackoverflow.com/questions/217253

  •  03-07-2019
  •  | 
  •  

質問

要件は次のとおりです。

使いやすいように、8〜10文字の英数字である必要があります。これらは、データベースに一意のキーとして保存されます。私は主キーとしてGUIDを使用しているため、これらの一意のIDを生成するためにGUidを使用するオプションが望ましいでしょう。

Guidを取得して8文字の一意の文字列に変換するbase-nコンバーターの行について考えています。

非常に頻繁に呼び出されるため、短く軽量なアルゴリズムを推奨します。

役に立ちましたか?

解決

ベース36。は、文字と数字を処理できるという点で検討する必要があります。 セットからI(目)およびO(Oh)を削除して、1(1)および0(ゼロ)と混同しないようにすることを検討してください。 2とZについても文句を言う人もいます。

他のヒント

8 characters - perfectly random - 36^8 = 2,821,109,907,456 combinations
10 characters - perfectly random - 36^10 = 3,656,158,440,062,976 combinations
GUID's - statistically unique* - 2^128 = 340,000,000,000,000,000,000,000,000,000,000,000,000 combinations

* GUIDは常に100%ユニークですか? [stackoverflow]

GUIDの問題->文字変換; GUIDは統計的に一意ですが、サブセットを使用することにより、ランダム性が低下し、衝突の可能性が高まります。確かに、ユニークではないSKUを作成する必要はありません。


ソリューション1:

オブジェクトおよびビジネスルールに関連するデータを使用してSKUを作成します。

i.e。オブジェクトを一意にする(自然キー)になる属性の小さな組み合わせが存在する可能性があります。自然キーの要素を結合し、エンコードおよび圧縮してSKUを作成します。多くの場合、必要なのは日時フィールド(つまり、CreationDate)とこれを実現するためのいくつかの他のプロパティだけです。 SKUの作成には多くの穴がある可能性がありますが、SKUの方がユーザーにより関連しています。

仮に:

Wholesaler, product name, product version, sku
Amazon,     IPod Nano,    2.2,             AMIPDNN22
BestBuy,    Vaio,         3.2,             BEVAIO32

ソリューション2:

ある範囲の数字を予約し、それらを順番に解放し、同じ数字を2回返さない方法。それでも範囲内に穴ができてしまいます。問題になるほど十分なSKUを生成する必要はありませんが、要件がこれを考慮していることを確認してください。

実装は、カウンタを持つデータベースに key テーブルを持つことです。カウンターはトランザクションで増分されます。重要な点は、1ずつ増加するのではなく、ソフトウェアのメソッドがブロックを取得することです。 pseudo-c#-codeは次のとおりです。

-- what the key table may look like
CREATE TABLE Keys(Name VARCHAR(10) primary key, NextID INT)
INSERT INTO Keys Values('sku',1)

// some elements of the class
public static SkuKeyGenerator 
{
    private static syncObject = new object();
    private static int nextID = 0;
    private static int maxID = 0;
    private const int amountToReserve = 100;

    public static int NextKey()
    {
        lock( syncObject )
        {
            if( nextID == maxID )
            {
                ReserveIds();
            }
            return nextID++;
        }
    }
    private static void ReserveIds()
    {
        // pseudocode - in reality I'd do this with a stored procedure inside a transaction,
        // We reserve some predefined number of keys from Keys where Name = 'sku'
        // need to run the select and update in the same transaction because this isn't the only
        // method that can use this table.
        using( Transaction trans = new Transaction() ) // pseudocode.
        {
             int currentTableValue = db.Execute(trans, "SELECT NextID FROM Keys WHERE Name = 'sku'");
             int newMaxID = currentTableValue + amountToReserve;
             db.Execute(trans, "UPDATE Keys SET NextID = @1 WHERE Name = 'sku'", newMaxID);

             trans.Commit();

             nextID = currentTableValue;
             maxID = newMaxID;
        }
    } 

ここでの考え方は、キー範囲を取得するのは高価な操作なので、コードがデータベースに頻繁にアクセスしないように十分なキーを予約することです。キーの損失(アプリケーションの再起動)とキーの使いすぎとデータベースへの戻りのバランスを取るために予約する必要があるキーの数を十分に把握する必要があります。この単純な実装には、失われたキーを再利用する方法はありません。

この実装はデータベースとトランザクションに依存しているため、アプリケーションを同時に実行でき、データベースに頻繁にアクセスすることなく、すべてが一意のキーを生成できます。

上記は、パターンの key table 、222ページに基づいています。エンタープライズアプリケーションアーキテクチャ(ファウラー)。このメソッドは通常、データベースID列を必要とせずに主キーを生成するために使用されますが、目的に合わせてどのように調整できるかを確認できます。

「ユーザーフレンドリー」を探している場合単純に短い/英数字にするのではなく、単語全体を使用してみてください。したがって、次のようになります。

words = [s.strip().lower() for s in open('/usr/share/dict/canadian-english') if "'" not in s]
mod = len(words)

def main(script, guid):
    guid = hash(guid)

    print "+".join(words[(guid ** e) % mod] for e in (53, 61, 71))

if __name__ == "__main__":
    import sys
    main(*sys.argv)

次のような出力が生成されます:

oranjestad+compressing+wellspring
padlock+discommoded+blazons
pt+olenek+renews

おもしろいです。それ以外の場合は、guidの最初の8〜10文字またはguidのsha1 / md5ハッシュを取得するのがおそらく最善の策です。

動作する可能性のある最も単純なものは、値が必要になるたびに増分されるカウンターです。 8桁(左ゼロ詰め)で、1億の可能な値00000000から99999999が得られます(ただし、000-000-00のように、人間が読みやすいようにスペースまたはハイフンを挿入できます)。

1億個を超える値が必要な場合は、長さを増やすか、別の位置に文字を使用します。 A0A0A0A0からZ9Z9Z9Z9を使用すると、45億を超える可能な値(4,569,760,000)が利用可能になります。長い整数を取り、そのようなエンコーディングを生成するのは簡単なコードです(右端の桁にmod 10、右端の文字に10による除算、それからmod 26など)。燃焼するメモリがある場合、最速の方法カウンタをmod 260配列に変換し、各mod 260値を2文字の文字列(「A0」、「A1」、「A2」など)の配列へのインデックスとして使用します。 A9」、「B0」、「B1」などから「Z9」まで)。

ベース36の問題(別の返信で言及)は、読者が同様の文字(1対I、0対O、2対Z、5対S)の混乱を心配する必要があるだけでなく、また、読者が不快な、またはわいせつな単語または略語のスペルとして知覚する可能性のある隣接する文字の組み合わせについても説明します。

CRC32ハッシュアルゴリズムを試すこともできます。 CRC32は8文字の文字列を生成します。

http://en.wikipedia.org/wiki/Cyclic_redundancy_check

http://textop.us/Hashing/CRC

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top