Bit status encoding

Snyke

Well-known member
ID: 348381
L
27 Mai 2009
400
28
Wollte mal eure meinung zu dem altbekannten bit-status encoding wissen wenn's um MySQL geht.

Im grunde will ich moeglichst effizient viele boolean values speichern und die updaten koennen. Was ich dazu mach is ich erstell eine einzelne column die einfach nur ein unzigned integer is (binary ginge auch) und dann werden je nach bit position ein anderer status gespeichert.

Also das ganze kann man sich so vorstellen:

Code:
set_status($status, $value, $position){
  if($value)
    $status = $status | (1 << $position);
  else
    $status = $status & !(1 << $position);
}

Code:
get_status($status, $position){
  return $status >> $position & 1;
}

Was man bekommt ist einen integer der die verschiedenen werte darstellt. Ich hab' nicht vor die column zu indexieren und ich werd' auch nicht drueber selecten. Spricht irgendwas gegen das Format?
 
Ob du den Integer nach PHP holst und dort Bit-Operationen ausführst, oder direkt in der DB die Bit-Operationen nutzst, ist egal.

Es macht nur dann einen Unterschied, wenn du alle Datensätze mit Bit 3, 6 gesetzt und Bit 1 und 8 nicht gesetzt haben willst.
Du hast zwar keine Optimierung, bist aber immer noch um Meilen schneller, als wenn du einfach alle Datensätze holst und in PHP guckst, wer passt, oder ob du in MySQL schon mit einer WHERE-Klausel nur die nötigen Zeilen erschlägst.
 
Hm, da hast du wohl recht. Die bit-operationen von mysql hatte ich voll uebersehen. Aber im ende bleibt die frage dieselbe: ist es sinnvoll oder nur ein billiger hack?
 
Aber im ende bleibt die frage dieselbe: ist es sinnvoll oder nur ein billiger hack?
Kommt ganz auf die Betrachtung drauf an.

Wenn du z.B. ein Rechtesystem programmierst und dir die einzelnen Rechte in einer Bitmaske darstellst, dann ist das gut und sogar effektiver, als wenn du jedem Recht ein eigenes Attribut einräumst.

Wenn du aber Bitpopelei veranstaltest, weil du dir einbildest die 6 Lottozahlen +1 Zusatzzahl (1 bis 49, d.h. 6bit), gesamt 42bit, in einen 64bit-BIGINT stecken zu wollen, dann is das freilich ein absolutes No-Go.
 
Also in meinem konkreten Fall ist's ein bettel script dass je nach besucher moeglichkeiten verguetet. Moeglichkeiten sind so sachen wie "werden bilder geladen", "wird javascript ausgefuehrt", "werden iframes geladen", "wird die seite bereits in einem frame geladen", etc...
Je nachdem bekommt der bettelnde dann mehr oder weniger Punkte verguetet. Das ganze mach ich um besser einschaetzen zu koennen wieviel der besucher fuer mich wert ist, denn wenn er keine bilder laedt, keine iframes laedt und kein js anhat wird er wahrscheinlich auch nicht meine Werbung laden.
 
Da würd ich dann schon ne Bitmaske einsetzen.

Allerdings nur, wenn diese Felder nicht woanders noch verwendet werden. Wenn du weitere Relationen hast, die auf diesen Tests ("werden bilder geladen", "wird javascript ausgefuehrt", "werden iframes geladen", "wird die seite bereits in einem frame geladen") Daten sammeln und zwischen den Relationen Beziehungen bestehen, dann nicht, sonst verlierst du die Möglichkeit, ordentlich zu JOINen.

dickes Edit:
Du kannst ja den SET-Datentyp in MySQL nehmen :doh:
Dann erübrigt sich die Diskussion eh :)
 
dickes Edit:
Du kannst ja den SET-Datentyp in MySQL nehmen :doh:
Dann erübrigt sich die Diskussion eh :)

nein, tut es nicht ;)
Indxe auf dem SET-Datentyp funktionieren nicht, wie du es erwartest ;) Ein Index kann nur genutzt werden wenn du jedes der Attribute mit einem equals-Check prüfst also eigentlich ist es haargenau das gleiche wie die Bitgeschichte ;)
Ich kann auch nicht nur Datensätze finden die Bit 11 auf 1 haben, sondern kann nur nach einem bestimmten Werpaar der Bits prüfen (und dabei müssen alle Bits gesetzt werden).

Gibt deswegen sogar extra einen Artikel bei MySQL dazu ;)
 
Naja, ich denke dass bei der ganzen Geschichte es keinen Sinn macht ueberhaupt die encodeten optionen als criteria in der query zu verwenden. Da sollte man wirklich einzelne Spalten nehmen und diese dann indexen.

Optimal ist ein bit-encoding wenn man die optionen selected, aber ueber andere Schluessel sucht. Z.B: ich will alle bettel anfragen der letzten stunde und diese dann vergueten, also selektier ich die optionen und user id, suche aber nur solche Zeilen raus die in der letzten Stunde eingetragen wurden (timestamp spalte), ich kann dann die optionen auslesen und entschluesseln. Dazu sollte die methode optimal sein.

Wo es allerdings keinen Sinn macht ist wenn ich alle bettel events auslesen will die frames unterstuetzt haben, also die optionen als criteria nennen :ugly: