74 Stimmen

Was sind die Leistungsverbesserungen von Sequential Guid gegenüber dem Standard Guid?

Hat jemand jemals die Leistung von Sequential Guid vs. Standard Guid gemessen, wenn sie als Primärschlüssel in einer Datenbank verwendet werden?


Ich sehe keine Notwendigkeit dafür, dass eindeutige Schlüssel erratbar oder nicht erratbar sein müssen. Sie von einer Web-Benutzeroberfläche oder an anderer Stelle zu übergeben, scheint an sich schon eine schlechte Praxis zu sein und ich sehe nicht, wie die Verwendung eines Guid die Dinge verbessern kann (wenn dies der Fall ist, verwenden Sie einen echten Zufallszahlengenerator mit den richtigen Kryptofunktionen des Frameworks).
Die anderen Punkte sind durch meinen Ansatz abgedeckt, ein Sequential Guid kann aus dem Code generiert werden, ohne auf die Datenbank zugreifen zu müssen (auch wenn dies nur für Windows gilt) und er ist eindeutig in Zeit und Raum.
Und ja, die Frage wurde gestellt, um sie zu beantworten, um denjenigen, die Guids für ihre PK gewählt haben, einen Weg zu geben, die Datenbanknutzung zu verbessern (in meinem Fall hat dies den Kunden ermöglicht, eine viel höhere Arbeitslast zu bewältigen, ohne die Server ändern zu müssen).

Es scheint, dass Sicherheitsbedenken eine Rolle spielen, in diesem Fall verwenden Sie keine Sequential Guid oder, noch besser, verwenden Sie Standard Guid für PKs, die von Ihrer Benutzeroberfläche hin und her übergeben werden, und Sequential Guid für alles andere. Wie immer gibt es keine absolute Wahrheit, ich habe auch die Hauptantwort bearbeitet, um dies widerzuspiegeln.

4voto

Mitch Wheat Punkte 287474

Schauen Sie sich COMBs von Jimmy Nilsson an: eine Art GUID, bei der eine Anzahl von Bits durch einen wert ähnlich einem Zeitstempel ersetzt wurde. Das bedeutet, dass die COMBs geordnet werden können und bei Verwendung als Primary Key zu weniger Indexseitenspalten führen, wenn neue Werte eingefügt werden.

Siehe auch: Ist es in Ordnung, einen uniqueidentifier (GUID) als Primärschlüssel zu verwenden?

Ja, eine Spalte für uniqueidentifier (GUID) kann als Primärschlüssel in Ordnung sein, ABER sie ist keine besonders gute Wahl für den geclusterten Index. In vielen Fällen ist es besser, den geclusterten Index auf einer Spalte (oder Spalten) zu erstellen, die wahrscheinlich bei Bereichssuchen verwendet werden, und einen nicht geclusterten Index auf die GUID-Spalte zu erstellen.

2 Stimmen

Ich bin ein wenig skeptisch gegenüber COMBs und ähnlichen Techniken, weil "GUIDs global eindeutig sind, aber Teilzeichenfolgen von GUIDs nicht": blogs.msdn.com/oldnewthing/archive/2008/06/27/8659071.aspx

7 Stimmen

GUIDs sind statistisch eindeutig. Das heißt, die Chancen auf eine Kollision sind sehr gering. Ein COMB opfert einige Bits der 128 verfügbaren in einem GUID. Ja, die Chancen auf eine Kollision sind höher, aber immer noch extrem niedrig.

1 Stimmen

Der ganze Sinn von guids ist, dass sie eine höhere Wahrscheinlichkeit für globale Eindeutigkeit haben als eine ganze Zahl. Diese Wahrscheinlichkeit muss nicht 100% betragen. Wenn Sie jedoch einen COMB-GUID verwenden, erhöht sich die Wahrscheinlichkeit einer Kollision, ist jedoch immer noch um viele Größenordnungen geringer als bei Verwendung einer Identitätsspalte.

4voto

Sklivvz Punkte 29602

Wenn Sie sequenzielle GUIds verwenden müssen, kann SQL Server 2005 sie mit der Funktion NEWSEQUENTIALID() für Sie generieren.

Allerdings da der grundlegende Zweck von GUIds darin besteht, Schlüssel (oder alternative Schlüssel) zu generieren, die nicht erraten werden können (um zum Beispiel zu verhindern, dass Personen geratene Schlüssel auf GETs übergeben), sehe ich nicht, wie anwendbar sie sind, da sie so leicht erraten werden können.

Von MSDN:

Wichtig:
Wenn Datenschutz eine Rolle spielt, verwenden Sie diese Funktion nicht. Es ist möglich, den Wert der nächsten generierten GUID zu erraten und damit auf Daten zuzugreifen, die mit dieser GUID verknüpft sind.

6 Stimmen

Ich wiederhole, ich sehe Guid nicht als Mittel zur Erzeugung von Schlüsseln, die nicht erraten werden können, sondern als Möglichkeit, Schlüssel zu haben, die sowohl zeitlich als auch räumlich eindeutig sind und leicht repliziert werden können. Wenn Datenschutz wichtig ist, sollte ein anderer Ansatz verwendet werden (echte Zufallszahlen)

4voto

Dennis Punkte 729

OK, Ich bin endlich an diesem Punkt im Design und in der Produktion angekommen.

Ich generiere eine COMB_GUID, bei der die oberen 32 Bits auf den Bits 33 bis 1 der Unix-Zeit in Millisekunden basieren. Es gibt also alle 2 Millisekunden 93 Bits Zufall und das Überlaufen der oberen Bits erfolgt alle 106 Jahre. Die tatsächliche physische Darstellung der COMB_GUID (oder Typ-4-UUID) ist eine Base64-codierte Version der 128 Bits, was eine Zeichenfolge von 22 Zeichen ergibt.

Beim Einfügen in Postgres ist das Verhältnis der Geschwindigkeit zwischen einer vollständig zufälligen UUID und einer COMB_GUID zugunsten der COMB_GUID vorteilhaft. Die COMB_GUID ist über mehrere Tests auf meiner Hardware 2X schneller, für einen Test mit einer Million Datensätzen. Die Datensätze enthalten die ID (22 Zeichen), ein String-Feld (110 Zeichen), eine Double-Precision- und eine INT-Zahl.

In ElasticSearch gibt es KEINEN erkennbaren Unterschied zwischen den beiden beim Indexieren. Ich werde trotzdem COMB_GUIDs verwenden, falls der Inhalt irgendwo in der Kette in BTREE-Indizes gelangt, da der Inhalt zeitbezogen ist oder auf dem ID-Feld vor sortiert werden kann, was IST zeitbezogen und teilweise sequentiell, es wird die Geschwindigkeit erhöhen.

Ziemlich interessant. Der Java-Code zum Erstellen einer COMB_GUID befindet sich unten.

import java.util.Arrays;
import java.util.UUID;
import java.util.Base64; //Nur verfügbar in Java 8+
import java.util.Date;

import java.nio.ByteBuffer; 

private ByteBuffer babuffer = ByteBuffer.allocate( (Long.SIZE/8)*2 );
private Base64.Encoder encoder = Base64.getUrlEncoder();
public  String createId() {
    UUID uuid = java.util.UUID.randomUUID();
        return uuid2base64( uuid );
}

public String uuid2base64(UUID uuid){ 

    Date date= new Date();
    int intFor32bits;
    synchronized(this){
    babuffer.putLong(0,uuid.getLeastSignificantBits() );
    babuffer.putLong(8,uuid.getMostSignificantBits() );

            long time=date.getTime();
    time=time >> 1; // macht es alle 2 Millisekunden
            intFor32bits = (int) time; // rollt alle 106 Jahre + 1 Monat seit Epoch über
            babuffer.putInt( 0, intFor32bits);

}
    //Verursacht dies ein Memory-Leck?
    return encoder.encodeToString( babuffer.array() );
}

}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X