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
* Is a GUID unique 100% of the time? [stackoverflow]
Problem z GUID - konwersja> znaków; podczas gdy GUID jest statystycznie unikalny, biorąc dowolny podzbiór, zmniejszasz losowość i zwiększasz ryzyko kolizji. Na pewno nie chcesz tworzyć nie-unqiue SKU.
Rozwiązanie 1:
Tworzenie SKU wykorzystując dane odnoszące się do reguł i obiektów biznesowych.
tj. Prawdopodobnie istnieje mała kombinacja atrybutów, które czynią obiekt niepowtarzalnym (a natural key). Połącz elementy klucza naturalnego, zakoduj i skompresuj je, aby utworzyć SKU. Często potrzebne jest tylko pole daty i czasu (np. CreationDate) i kilka innych właściwości, aby to osiągnąć. Prawdopodobnie masz dużo dziur w tworzeniu sku, ale sku są bardziej odpowiednie dla twoich użytkowników.
teoretycznie:
Wholesaler, product name, product version, sku
Amazon, IPod Nano, 2.2, AMIPDNN22
BestBuy, Vaio, 3.2, BEVAIO32
Roztwór 2:
Sposób że rezerwuje zakres numerów, a następnie prowadzi się kolejno do ich uwolnienia, i nigdy nie powraca do tej samej liczby dwa. Wciąż możesz skończyć z dziurami w zasięgu. Prawdopodobnie nie musisz generować wystarczającej liczby sku, ale upewnij się, że pozwalają na to Twoje wymagania.
Implementacją jest posiadanie tabeli key
w bazie danych z licznikiem. Licznik jest inkrementowany w transakcji. Ważnym punktem jest to, że zamiast inkrementować o 1, metoda w oprogramowaniu chwyta blok. kod pseudo-C# jest następujący.
-- 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;
}
}
Chodzi o to, że zarezerwować wystarczającą ilość klawiszy tak, że kod nie wychodzi z bazy danych często, jak się kluczowy zakres jest kosztowna operacja. Musisz mieć dobry pomysł na liczbę kluczy, które musisz zarezerwować, aby zrównoważyć utratę klucza (restart aplikacji) i wyczerpanie kluczy zbyt szybko i powrót do bazy danych. Ta prosta implementacja nie ma możliwości ponownego użycia zgubionych kluczy.
Ponieważ ta implementacja opiera się na bazie danych i transakcjach, aplikacje mogą działać jednocześnie, a wszystkie generują unikalne klucze bez konieczności częstego odwiedzania bazy danych.
Uwaga powyższe jest luźno oparte na key table
, strona 222 z Patterns of Enterprise Application Architecture (Fowler). Metoda ta jest zwykle używana do generowania kluczy podstawowych bez potrzeby korzystania z kolumny tożsamości bazy danych, ale można zobaczyć, w jaki sposób można ją dostosować do własnych potrzeb.
Jest to prawdopodobnie najlepszy zakład, ale niestety 128-bitowy identyfikator GUID kończy się w dalszym ciągu ponad 20 znaków w bazie 36. Być może GUID nie jest najlepszym punktem wyjścia. –
Guid jest łatwo dostępny z moich obiektów modelu, więc uważam, że będzie to bardzo wygodne. – Mank
cóż, możesz przejść do A-Z i a-z i 0-9 do tej bazy 62. Być może to zadziała lepiej. – EvilTeach