Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[Java] hashCode als identifier in DB?

Pagina: 1
Acties:

  • Standeman
  • Registratie: November 2000
  • Laatst online: 23:44

Standeman

Prutser 1e klasse

Topicstarter
Dit is misschien een slecht idee, maar ik zit te overwegen om de hashcode() functie te gebruiken als identifier voor een bepaalde set aan gegevens.

De reden waarom ik dit wil gaan doen is omdat ik een vrij "random" set aan gegevens binnen krijg die ik wil gaan opslaan. Echter, als ik eenzelfde set aan gegevens binnen krijg, moet ik wel een id kunnen genereren, om hem later weer terug te vinden.

Om het wat duidelijker te maken hier een klein voorbeeldje van het object dat ik aangeboden krijg.
Java:
1
2
3
4
5
6
7
8
9
10
11
public class Device
{
    public String brand;
    public String type;
    private String macaddress;
    private String imei;
    private String serialNumber;
    private String ip;
    private Date timestamp;
//getters & setters
}


Nu kan het zijn dat bij device A brand / imei / serialnumber ingevuld is. Bij device B ip / serialnumber en dan weer bij device C alleen het macaddress.
De combinatie zal per device altijd hetzelfde zijn. Dus waneer device A weer wordt aangeboden, zal die hetzelfde brand / imei / serialnumber hebben.

Dit wordt overigens gebruikt om te zien op welke tijdstippen er door device A (de timestamp in het object) contact is opgenomen met 1 van onze systemen.

Nu wil ik voor elk uniek device een id gaan generen op basis van de ingevulde velden. Ik zit nu te denken om hashcode van het object te berekenen en dat te gebruiken als identifier voor mijn device (misschien nog met een technische primary key erbij). Echter vraag ik me af wat de kans op collisions is wanneer ik dit daadwerkelijk op deze manier implementeer. Ook voelt het als misbruik van de hashcode functie.

een voorbeeldje van de hashcode functie zal dan zijn:
Java:
1
2
3
4
5
6
7
8
9
    @Override
    public int hashCode()
    {
        int hash = 5;
        hash = 97 * hash + (this.brand != null ? this.brand.hashCode() : 0);
        hash = 97 * hash + (this.type != null ? this.type.hashCode() : 0);
        // etc....
        return hash;
    }


Een andere oplossing kan zijn om van alle aangewezen velden een compound key in de DB te maken, maar daar wordt ik ook niet vrolijk van. Dit is namelijk een simpel voorbeeld, in de realiteit kunnen het wel meer dan 10 betreffen en ik durf even niet te voorspellen wat dit met de performance van MySQL gaat doen.

Maar misschien ligt de heilige graal op een hele andere plek. Ik ben iig benieuwd naar commentaar :)

The ships hung in the sky in much the same way that bricks don’t.


  • HMS
  • Registratie: Januari 2004
  • Laatst online: 17-11 00:33

HMS

Aangenomen dat je een uniform gedistribueerde hashcode hebt, dan is er een 50/50 collision kans bij 2^16 objecten (oftewel 1 op 65536). Dat lijkt me een beetje te klein om nuttig te zijn.

Daarnaast geldt ook (voor Java hashcodes), x.equals(y) -> x.hashCode() == y.hashCode(), maar het omgekeerde (x.hashCode() == y.hashCode() -> x.equals(y)), geldt niet!

Ik denk dat je beter een cryptografische hashcode als SHA-1, of SHA-256 kan gebruiken. De collision kans is dan 1 op 2^80 of 1 op 2^128 respectievelijk. Een stuk beter dan 1 op 2^16 ;)

  • Standeman
  • Registratie: November 2000
  • Laatst online: 23:44

Standeman

Prutser 1e klasse

Topicstarter
Hmmm, ja. Daar heb je zeker een punt. En het gaat alleen om insert / update acties. Dus de overhead van (bijv. SHA-1) zal redelijk beperkt blijven t.o.v. hashcode(). Volgens mij is er qua performance ook niet echt een verschil tussen int of varchar in mysql. (aangezien ik denk ik de hashes als string zal opslaan).

Het worden er (waarschijnlijk) wel 50.000+ sha-1 berekeningen per dag. Ik ben wel benieuwd of mijn server dit gaat trekken..

[ Voor 18% gewijzigd door Standeman op 10-06-2013 15:21 ]

The ships hung in the sky in much the same way that bricks don’t.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-11 03:08
Het lijkt me dat als je weet welke velden je moet hashen om de identiteit van een object vast te stellen, je automatisch ook weet welke velden er in de primary key thuishoren :?

Als je een zinnige hash-functie gebruikt (en dat is SHA-1) lijkt me dat een hashcode als key prima kan werken, maar ik zie eigenlijk niet echt het voordeel daarvan. Je verplaatst dan immers de complexiteit van de de databaseserver naar de client.

  • Standeman
  • Registratie: November 2000
  • Laatst online: 23:44

Standeman

Prutser 1e klasse

Topicstarter
Soultaker schreef op maandag 10 juni 2013 @ 15:32:
Het lijkt me dat als je weet welke velden je moet hashen om de identiteit van een object vast te stellen, je automatisch ook weet welke velden er in de primary key thuishoren :?

Als je een zinnige hash-functie gebruikt (en dat is SHA-1) lijkt me dat een hashcode als key prima kan werken, maar ik zie eigenlijk niet echt het voordeel daarvan. Je verplaatst dan immers de complexiteit van de de databaseserver naar de client.
Tja, dan zal het over een hoop velden een unique index moeten leggen. Nu ik er even over zit na te denken zou het eigenlijk wel handiger zijn.
Het enige nadeel is dat het misschien wat minder overzichtelijk wordt door het aantal velden waar de index overheen ligt als ik in de db zit te kijken, maar het scheelt wel werk dat ik er verder in mijn software er geen rekening mee hoef te houden.

offtopic:
Als developer probeer ik wel vaker DB zaken in mijn software te regelen.. lastige eigenschap :P

The ships hung in the sky in much the same way that bricks don’t.


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 22-11 13:46

Janoz

Moderator Devschuur®

!litemod

Je moet ook helemaal niet veel in de DB kijken. Een DB is bedoeld om door software gelezen te worden. Daar moet ie voor worden geoptimaliseerd. Dat mensen er nog leuk in kunnen lezen is een leuke nice to have. (Wat trouwens niet een vrijbrief is om je kolomnamen maar c1 t/m c22 te noemen)

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Feanathiel
  • Registratie: Juni 2007
  • Niet online

Feanathiel

Cup<Coffee>

Standeman schreef op maandag 10 juni 2013 @ 14:34:
Dit is misschien een slecht idee, maar ik zit te overwegen om de hashcode() functie te gebruiken als identifier voor een bepaalde set aan gegevens.

[...]
Het lijkt mij sowieso niet handig om hashCode() voor identificatie te gebruiken. Een hashcode is alleen gegarandeerd hetzelfde binnen een lifecycle van een applicatie. Het heeft dan ook geen zin om dit in de database op te slaan omdat je er geen conclusies over kunt trekken.

http://docs.oracle.com/ja...ng/Object.html#hashCode():
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.

  • ThomasG
  • Registratie: Juni 2006
  • Laatst online: 18:54
Standeman schreef op maandag 10 juni 2013 @ 15:15:
Hmmm, ja. Daar heb je zeker een punt. En het gaat alleen om insert / update acties. Dus de overhead van (bijv. SHA-1) zal redelijk beperkt blijven t.o.v. hashcode(). Volgens mij is er qua performance ook niet echt een verschil tussen int of varchar in mysql. (aangezien ik denk ik de hashes als string zal opslaan).
Je gaat dit waarschijnlijk wel als sleutel/index gebruiken. Houd er rekening mee dat een varchar (indien groter dan 4 tekens) meer ruimte in neemt dan een int. Dat betekend dat de database minder per index page kwijt kan, wat er dus voor zorgt dat je performance bij tabellen met veel records achteruit gaat.

Ik weet niet hoe je database verder in elkaar steekt. Maar als je het ook gaat gebruiken als vreemde sleutel naar andere tabellen, zou ik onder de motorkap gewoon een geoptimaliseerd type gebruiken als PK, en de hash slechts als lookup gebruiken (indien je dat echt wilt). Dat kan indien je database groeit heel wat paging overhead besparen, en krijg je dus betere performance.

Ik ben sowieso niet zo'n voorstander van hashes gebruiken als primaire sleutel, tenzij de DBMS daar een geoptimaliseerd type voor heeft. Een SHA-1 hash bevat bijvoorbeeld alleen van 0 t/m 9 en A t/m F. Daar heb je geen hele byte nodig per teken. Daar heb je aan een halve byte (nibble) per teken voldoende. Zo kun je dus meer kwijt op je index pages. Daarnaast zijn ze 'te random' waardoor je vaak je index opnieuw moet clusteren, omdat je anders vrijwel niks meer aan je index hebt. Of je fill factor moet omlaag, maar krijg je weer meer overhead.

  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 16:33
Je zoekactie is gewoon een wat complexer query dan normaal. Vanaf dat moment weet je je interne ID waarmee je verder kunt werken. Ik zou dus niets doen met hashen maar gewoon zodra het juiste object gevonden hebt verder werken met een interne auto-increment ID.

Het hashen is net zoveel gedoe als gewoon zoeken op meerdere kolommen. Dus die stap er tussen voegt niets toe imo.

Hoe zeker ben je er van dat die attributen van een product een unieke combinatie opleveren? Houd er rekening mee dat de fabrikant ook fouten kan maken en dat je dus mogelijk 2x "hetzelfde" apparaat kunt krijgen. Het is gewoon externe invoer dus daar rekening mee houden lijkt me zeker niet verkeerd.

Als dat voorkomt kan je 2 records maken met dezelfde eigenschappen (maar andere id) waarbij je bijvoorbeeld dus een logentry of waarschuwing kunt genereren.

  • Standeman
  • Registratie: November 2000
  • Laatst online: 23:44

Standeman

Prutser 1e klasse

Topicstarter
Feanathiel schreef op maandag 10 juni 2013 @ 16:52:
[...]


Het lijkt mij sowieso niet handig om hashCode() voor identificatie te gebruiken. Een hashcode is alleen gegarandeerd hetzelfde binnen een lifecycle van een applicatie. Het heeft dan ook geen zin om dit in de database op te slaan omdat je er geen conclusies over kunt trekken.

http://docs.oracle.com/ja...ng/Object.html#hashCode():

[...]
Dan is hashcode sowieso een no-go. Want dan plaats ik de hashcode inderdaad buiten de applicatie lifecycle en dat is vragen om problemen.


Maar goed, ik ben er uit. Ik ga geen kunstmatige id's gebruiken (via sha1 / hashcode / whatever) om mijn objecten te identificeren. Volgens mij creëer ik dan problemen die bijzonder lastig uit te pluizen zijn.
Dus gewoon een unique index op de benodigde kolommen met daarnaast een technische primaire sleutel. Sommige queries worden inderdaad wel 'lastiger', maar lijkt me zeker geen overkomelijk probleem.
djluc schreef op maandag 10 juni 2013 @ 18:08:
Hoe zeker ben je er van dat die attributen van een product een unieke combinatie opleveren? Houd er rekening mee dat de fabrikant ook fouten kan maken en dat je dus mogelijk 2x "hetzelfde" apparaat kunt krijgen. Het is gewoon externe invoer dus daar rekening mee houden lijkt me zeker niet verkeerd.

Als dat voorkomt kan je 2 records maken met dezelfde eigenschappen (maar andere id) waarbij je bijvoorbeeld dus een logentry of waarschuwing kunt genereren.
Sowieso draait op verreweg de meeste apparaten onze software (die overigens niet of zeer moeilijk kunnen updaten), dus het is redelijk bekend welke info ze prijs geven bij een request en hoe stabiel dat is.
Overigens zal het niet zo heel groot probleem zijn wanneer er 1 device 2 regels krijgt. Dat valt vrij snel op en is vrij makkelijk te corrigeren. :)

The ships hung in the sky in much the same way that bricks don’t.


  • pedorus
  • Registratie: Januari 2008
  • Niet online
Standeman schreef op dinsdag 11 juni 2013 @ 09:16:
Maar goed, ik ben er uit. Ik ga geen kunstmatige id's gebruiken (via sha1 / hashcode / whatever) om mijn objecten te identificeren. Volgens mij creëer ik dan problemen die bijzonder lastig uit te pluizen zijn.
Wel eens Git gebruikt? In essentie gebruikt Git ook hashcodes voor id's. De kans dat dit een probleem geeft is zodanig klein dat het niet relevant is. (Tenzij wellicht als er apart op gestuurd zou worden.)
Each object is identified by a SHA-1 hash of its contents. Git computes the hash, and uses this value for the object's name. The object is put into a directory matching the first two characters of its hash. The rest of the hash is used as the file name for that object.
Behalve dan dat de definitie die Java gebruikt niet bruikbaar is, is het concept dus prima.

[ Voor 3% gewijzigd door pedorus op 11-06-2013 11:30 ]

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1