Frage

verwende ich varchar (36) oder gibt es bessere Möglichkeiten, es zu tun?

War es hilfreich?

Lösung

Meine DBA fragte mich, wenn ich über die beste Art und Weise gefragt GUIDs zu speichern für meine Objekte, warum ich brauchte 16 Bytes zu speichern, wenn ich die gleiche Sache in 4 Bytes mit einer Integer tun könnte. Da er diese Herausforderung für mich löschte es dachte, ich wäre jetzt ein guter Zeitpunkt, es zu erwähnen. Dass gesagt wird ...

Sie können speichern Sie eine als CHAR guid (16) binär, wenn Sie die optimale Nutzung von Speicherplatz machen wollen.

Andere Tipps

Ich würde speichern Sie es als char (36).

Zusätzlich zu der Antwort von ThaBadDawg, verwenden Sie diese praktischen Funktionen (dank eine weiser collegue von mir) von 36 Zeichenfolge zu einem Byte-Array von 16 zurück.

DELIMITER $$

CREATE FUNCTION `GuidToBinary`(
    $Data VARCHAR(36)
) RETURNS binary(16)
DETERMINISTIC
NO SQL
BEGIN
    DECLARE $Result BINARY(16) DEFAULT NULL;
    IF $Data IS NOT NULL THEN
        SET $Data = REPLACE($Data,'-','');
        SET $Result =
            CONCAT( UNHEX(SUBSTRING($Data,7,2)), UNHEX(SUBSTRING($Data,5,2)),
                    UNHEX(SUBSTRING($Data,3,2)), UNHEX(SUBSTRING($Data,1,2)),
                    UNHEX(SUBSTRING($Data,11,2)),UNHEX(SUBSTRING($Data,9,2)),
                    UNHEX(SUBSTRING($Data,15,2)),UNHEX(SUBSTRING($Data,13,2)),
                    UNHEX(SUBSTRING($Data,17,16)));
    END IF;
    RETURN $Result;
END

$$

CREATE FUNCTION `ToGuid`(
    $Data BINARY(16)
) RETURNS char(36) CHARSET utf8
DETERMINISTIC
NO SQL
BEGIN
    DECLARE $Result CHAR(36) DEFAULT NULL;
    IF $Data IS NOT NULL THEN
        SET $Result =
            CONCAT(
                HEX(SUBSTRING($Data,4,1)), HEX(SUBSTRING($Data,3,1)),
                HEX(SUBSTRING($Data,2,1)), HEX(SUBSTRING($Data,1,1)), '-', 
                HEX(SUBSTRING($Data,6,1)), HEX(SUBSTRING($Data,5,1)), '-',
                HEX(SUBSTRING($Data,8,1)), HEX(SUBSTRING($Data,7,1)), '-',
                HEX(SUBSTRING($Data,9,2)), '-', HEX(SUBSTRING($Data,11,6)));
    END IF;
    RETURN $Result;
END
$$

CHAR(16) ist eigentlich ein BINARY(16), wählen Sie Ihren bevorzugten Geschmack

Um den Code besser zu folgen, nehmen Sie das Beispiel der Ziffer geordnete GUID unten angegeben. (Illegal-Zeichen werden zu Veranschaulichungszwecken verwendet - jeder Ort einen einzigartigen Charakter.) Die Funktionen der Bytereihenfolge Transformation eine Bitreihenfolge für überlegene Index Clustering zu erzielen. Der neu geordnet guid ist unter dem Beispiel gezeigt wird.

12345678-9ABC-DEFG-HIJK-LMNOPQRSTUVW
78563412-BC9A-FGDE-HIJK-LMNOPQRSTUVW

Bindestriche entfernt:

123456789ABCDEFGHIJKLMNOPQRSTUVW
78563412BC9AFGDEHIJKLMNOPQRSTUVW

char (36) wäre eine gute Wahl sein. Auch MySQL-UUID () Funktion kann verwendet werden, das gibt ein 36-Zeichen-Textformat (hex mit Bindestrichen), die für Abfragen solchen IDs aus der db verwendet werden kann.

"Better" hängt davon ab, was Sie Optimierung für.

Wie viel Pflege Sie Speichergröße / Leistung vs. einfache Entwicklung? Noch wichtiger ist - sind Sie genug GUIDs zu erzeugen, oder sie häufig genug zu holen, dass es wichtig ist

?

Wenn die Antwort „nein“ ist, ist char(36) mehr als gut genug, und es macht Speichern / Abrufen von GUIDs dead-einfach. Andernfalls binary(16) ist angemessen, aber Sie werden auf MySQL lehnen und / oder Ihre Programmiersprache der Wahl hin und her von der üblichen String-Darstellung zu konvertieren.

Binary (16) wäre gut, besser als die Verwendung von varchar (32).

Die GuidToBinary Routine von KCD geschrieben sollte in dem GUID-String der Zeitstempel-Konto für das Bit-Layout optimiert werden. Wenn die Zeichenfolge einen UUID Version 1 darstellen, wie die von der UUID () mysql Routine zurückgegeben, dann werden die Zeitkomponenten in Buchstaben eingebettet 1-G, mit Ausnahme der D.

12345678-9ABC-DEFG-HIJK-LMNOPQRSTUVW
12345678 = least significant 4 bytes of the timestamp in big endian order
9ABC     = middle 2 timestamp bytes in big endian
D        = 1 to signify a version 1 UUID
EFG      = most significant 12 bits of the timestamp in big endian

Wenn Sie in binäre konvertieren, ist die beste, um für die Indizierung wäre. EFG9ABC12345678D + der Rest

Sie wollen nicht von 12345678 bis 78563412 tauschen, weil Big-Endian bereits die beste binäre Index-Byte-Reihenfolge ergibt. Allerdings wollen Sie die wichtigsten Bytes vor den unteren Bytes bewegt. Daher geht EFG zuerst, gefolgt von den mittleren Bits und unteren Bits. Generieren Sie ein Dutzend oder so UUIDs mit UUID () über den Verlauf einer Minute, und Sie sollten sehen, wie diese, um den korrekten Rang ergibt.

select uuid(), 0
union 
select uuid(), sleep(.001)
union 
select uuid(), sleep(.010)
union 
select uuid(), sleep(.100)
union 
select uuid(), sleep(1)
union 
select uuid(), sleep(10)
union
select uuid(), 0;

/* output */
6eec5eb6-9755-11e4-b981-feb7b39d48d6
6eec5f10-9755-11e4-b981-feb7b39d48d6
6eec8ddc-9755-11e4-b981-feb7b39d48d6
6eee30d0-9755-11e4-b981-feb7b39d48d6
6efda038-9755-11e4-b981-feb7b39d48d6
6f9641bf-9755-11e4-b981-feb7b39d48d6
758c3e3e-9755-11e4-b981-feb7b39d48d6 

Die ersten beiden UUIDs wurden zeitlich am nächsten erzeugt. Sie unterscheiden sich nur in den letzten 3 Knabbereien des ersten Blocks. Dies sind die am wenigsten signifikanten Bits des Zeitstempels, was bedeutet, wollen wir sie nach rechts schieben, wenn wir dies zu einer Wende Byte-Array zu konvertieren. Als Gegenbeispiel ist die letzte ID die aktuellste, aber der Swapping-Algorithmus KCD wäre es vor dem 3. ID setzen (3e vor dc, letztes Bytes aus dem ersten Block).

Die richtige Reihenfolge für die Indizierung wäre:

1e497556eec5eb6... 
1e497556eec5f10... 
1e497556eec8ddc... 
1e497556eee30d0... 
1e497556efda038... 
1e497556f9641bf... 
1e49755758c3e3e... 

In diesem Artikel finden entsprechende Informationen: http://mysql.rjweb.org/doc.php / uUID

*** beachten Sie, dass ich teile nicht die Version knabbert von den hohen 12 Bits des Zeitstempels. Dies ist das D knabbert aus Ihrem Beispiel. Ich werfe es gerade vor. Also meine binäre Folge endet als DEFG9ABC und so weiter. Dies bedeutet, dass alle meine indizierten UUIDs mit dem gleichen knabbern beginnen. Der Artikel macht das Gleiche.

Für die, die gerade über diese stolpern, gibt es jetzt eine viel bessere Alternative als pro Forschung durch Percona.

Es besteht die UUID Brocken für eine optimale Indizierung neu zu organisieren, dann in binärer Umwandlung für reduzierte Lager.

Lesen Sie den ganzen Artikel hier

Ich würde vorschlagen, die Funktionen unter Verwendung, da die Erwähnten durch @ bigh_29 verwandelt meine guids in neue (aus Gründen, die ich nicht verstehe). Auch diese sind ein wenig schneller in den Tests habe ich auf meine Tabellen. https://gist.github.com/damienb/159151

DELIMITER |

CREATE FUNCTION uuid_from_bin(b BINARY(16))
RETURNS CHAR(36) DETERMINISTIC
BEGIN
  DECLARE hex CHAR(32);
  SET hex = HEX(b);
  RETURN LOWER(CONCAT(LEFT(hex, 8), '-', MID(hex, 9,4), '-', MID(hex, 13,4), '-', MID(hex, 17,4), '-', RIGHT(hex, 12)));
END
|

CREATE FUNCTION uuid_to_bin(s CHAR(36))
RETURNS BINARY(16) DETERMINISTIC
RETURN UNHEX(CONCAT(LEFT(s, 8), MID(s, 10, 4), MID(s, 15, 4), MID(s, 20, 4), RIGHT(s, 12)))
|

DELIMITER ;

Wenn Sie einen char / varchar Wert als Standard-GUID formatiert haben, können Sie einfach speichern Sie es als BINARY (16) mit der einfachen CAST (MyString AS BINARY16), ohne all die irrsinnig Sequenzen von CONCAT + SUBSTR.

BINARY (16) Felder sind im Vergleich / sortiert / indiziert viel schneller als Zeichenfolgen und nehmen auch zwei Mal weniger Platz in der Datenbank

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top