Ralf: nichtfortlaufende, eindeutige Nummer erzeugen

Hi,

in einem online Shop gibt es für jeden Auftrag eine fortlaufende, eindeutige Auftragsnummer.
Diese soll aber nicht nach außen kommuniziert werden damit man nicht auf die Anzahl der Aufträge schließen kann. Statt dessen soll eine eindeutige aber nicht fortlaufende Nummer als "externe" Auftragsnummer verwendet werden.

Ich möchte jetzt nicht über Sinn und Unsinn von so etwas diskutieren, sondern über die technische Umsetzung.

Die externe (EAN) und die interne (IAN) Auftragsnummer sollen in einer eindeutigen Relation zueinander stehen, d.h. ich muss aus der einen eindeutig die andere erzeugen können.

Ich dachte jetzt an folgendes:

Die Menge der in einem Jahr zu erzeugenden Nummer ist, sagen wir auf 1.000.000 begrenzt. So könnte die EAN aus einem variablen Teil + der Jahreszahl bestehen.
Dann erzeuge ich eine DB Tabelle mit den beiden Spalten EAN und IAN.
Diese fülle ich einmal wie folgt:
Ich erzeuge ein Array das die Zahlen 1-1.000.000 enthält. Mit einer Zufallsfunktion nehme ich ein Element, lösche es aus dem Array und füge es in die DB Tabelle als EAN zusammen mit der fortlaufenden IAN ein.

Wenn das Array nach 1.000.000 Schritten leer ist, enthält meine Tabelle eine eindeutige, nicht so ohne weiteres nachzuvollziehende Relation von EAN und IAN.

Was meint Ihr dazu?
Geht das auch eleganter?

MfG
Ralf

  1. Moin Ralf,

    Ich erzeuge ein Array das die Zahlen 1-1.000.000 enthält. Mit einer Zufallsfunktion nehme ich ein Element, lösche es aus dem Array

    Dieser Schritt ist überflüssig :-) Nimm einen Array und speichere, welche Ziffer zwischen 1 und 1000000 du schon hattest. Damit sparst du dir 1.000.000 Operationen zuzüglich zu den teuren Slice-Operationen.

    Was meint Ihr dazu?
    Geht das auch eleganter?

    Ich an deiner Stelle würde einen UNIQUE-Index über EAN legen und schlicht solange mit einem Zufallsgenerator eine Zufallszahl (innerhalb eines gewissen Wertebereichs) erzeugen und versuchen den Datensatz einzufügen, bis das einfügen nicht mehr an dem UNIQUE-Index scheitert. Damit hast du eine eindeutige, nicht fortlaufende Ziffer, das ganze frei von race conditions und Kollisionen.

    LG,
     CK

    1. Moin Ralf,

      Ich erzeuge ein Array das die Zahlen 1-1.000.000 enthält. Mit einer Zufallsfunktion nehme ich ein Element, lösche es aus dem Array

      Dieser Schritt ist überflüssig :-) Nimm einen Array und speichere, welche Ziffer zwischen 1 und 1000000 du schon hattest. Damit sparst du dir 1.000.000 Operationen zuzüglich zu den teuren Slice-Operationen.

      Was meint Ihr dazu?
      Geht das auch eleganter?

      Ich an deiner Stelle würde einen UNIQUE-Index über EAN legen und schlicht solange mit einem Zufallsgenerator eine Zufallszahl (innerhalb eines gewissen Wertebereichs) erzeugen und versuchen den Datensatz einzufügen, bis das einfügen nicht mehr an dem UNIQUE-Index scheitert. Damit hast du eine eindeutige, nicht fortlaufende Ziffer, das ganze frei von race conditions und Kollisionen.

      Ja, o.k. die Erzeugung der lookup table ist in meiner Ausführung nicht gerade optimal. Die muss aber nur einma erzeugt werden. Da kommt es auf eine Laufzeit von ein paar Sekunden nicht an.

      Im Laufenden Betrieb gibt sdann ja nur einen DB Zugriff. Wenn man über EAN und IAN je einen Index legt, sollte das recht performat sein.

      Die Frage ging mehr in die Rechung ob man nicht auch ohne so einen im Vorfeld gebaute lookup table eine eindeutige und nicht so leicht nachvollziehbare Abbildung von EAN <->IAN hinbekommt.

      MfG
      Ralf

      1. Moin Ralf,

        Die Frage ging mehr in die Rechung ob man nicht auch ohne so einen im Vorfeld gebaute lookup table eine eindeutige und nicht so leicht nachvollziehbare Abbildung von EAN <->IAN hinbekommt.

        Das ist abhängig von der Erzeugung der Zufallszahl. Aber generell würde ich erstmal sagen: ja.

        LG,
         CK

  2. Hi,

    ich verstehe deinen Aufbau und Ansatz nicht.

    Ich würde es so machen, dass in der Tabelle mit den Aufträgen IAN (auto-increment) der Primärschlüssel und eine extra Spalte EAN ist.
    Wenn ein neuer Auftrag in die Datenbank eingetragen wird, die EAN auf die aktuelle Zeit in Millisekunden setzen.
    Fertig.
    Dann brauchst du auch keine Tabelle die Prä-Auftraugserfassung komplett gefüllt sein muss.

    Oder übersehe ich da etwas?

    ~dave

    1. Moin dave,

      Dann brauchst du auch keine Tabelle die Prä-Auftraugserfassung komplett gefüllt sein muss.

      Vor allem mit 1.000.000 Mio Datensätze allein schon im ersten Jahr.

      Oder übersehe ich da etwas?

      Naja, in deinem Beispiel wäre die EAN aufsteigend. Aber ja, es gibt bessere Methoden.

      LG,
       CK

      1. Moin dave,

        Dann brauchst du auch keine Tabelle die Prä-Auftraugserfassung komplett gefüllt sein muss.

        Vor allem mit 1.000.000 Mio Datensätze allein schon im ersten Jahr.

        Wie kommst du jetzt auf eine Billion Datensätze?

        Gruß
        Kalk

        1. Moin Tabellenkalk,

          Vor allem mit 1.000.000 Mio Datensätze allein schon im ersten Jahr.

          Wie kommst du jetzt auf eine Billion Datensätze?

          Vertipper. Streiche das „Mio.“

          LG,
           CK

  3. Denk dir eine mathematische Funktion aus, die eine Zahl in eine andere umwandelt, so dass das Ergebnis wieder zurückrechenbar ist und nichts mehr über die Reihenfolge der ursprünglichen Zahlen aussagt.
    Oder eine die eine eindeutige Zahl berechnet die dann nicht mehr zurückrechenbar ist, die dann aber zum Auftrag als Kennung gespeichert wird.
    Zum Beispiel wäre c * x mod y so eine Funktion (x = Auftragsnummer), falls y eine Primzahl ist. Schau dir z.B. mal an was bei 67 * x mod 29 so alles rauskommt (für x < 29) und ob dir das "wirr" genug ist.

    Oder nimm eine Verschlüsselungsfunktion, verschlüssle die Auftragsnummer mit der und verwende das Ergebnis in Hexdarstellung. Das brauchst du dann nicht mal speichern, denn du kannst es wieder zurück-verschlüsseln.
    (ich würds aber trotzdem speichern, sicher ist sicher)

    1. Hallo,

      Denk dir eine mathematische Funktion aus, die eine Zahl in eine andere umwandelt, so dass das Ergebnis wieder zurückrechenbar ist und nichts mehr über die Reihenfolge der ursprünglichen Zahlen aussagt.

      sowas in der Art hätte ich auch vorgeschlagen. Mir würde da spontan eine Bit-Permutation nach einem festen Schema einfallen. Wenn man gut würfelt, sieht die resultierende Folge auf den ersten Blick schon ziemlich chaotisch aus. Lass uns beispielsweise immer die Bits 0/2, 1/4, 3/7 und 5/6 vertauschen:

      Original   Permutiert
         0           0
         1           4
         2          16
         3          20
         4           1
         5           5
         6          17
         7          21
        ...         ...

      Ciao,
       Martin

      --
      Ich stehe eigentlich gern früh auf.
      Außer morgens.
      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
  4. hi,

    Geht das auch eleganter?

    Du musst Das nicht Alles neu erfinden: Aus zwei bekannten Nummern eine Dritte erzeugen, die keinen Rückschluss auf die zwei erstgenannten Nummern zulässt, ja, das gibt es schon ;)

    Gugg mal nach Diffie Hellmann...

    Hotti

  5. Moin,

    ich hätte den timestamp benutzt.
    time() + 2 Zufallchars + interne Auftragsnummer.

    Dann hättest du sogar den Zeitpunkt der Bestellung in der Auftragsnummer.
    Denkbar wäre auch die Interne Kundennummer da noch rein zu packen oder andere interne Sachen. Dann wird das aber wieder zu lang...hmm...

    Hoffe ich konnte trotzdem helfen

    Gruß
    der einfach praktisch denkende
    T-Rex