Frage

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

War es hilfreich?

Lösung

GUID vs.Sequential GUID


Ein typisches Muster ist es Guid als PK für Tabellen zu verwenden, aber wie in anderen Diskussionen bezeichnet (siehe Vor- und Nachteile der GUID / UUID Datenbankschlüssel ) gibt es einige Performance-Probleme.
Dies ist ein typischer Guid Sequenz

f3818d69-2552-40b7-a403-01a6db4552f7
    7ce31615-FAFB-42c4-b317-40d21a6a3c60
    94732fc7-768e-4cf2-9107-f0953f6795a5
    
Probleme dieser Art von Daten sind: << br>     -

  • Breite Verteilungen von Werten
  • Fast randomically diejenigen
  • Index Nutzung ist sehr, sehr, sehr schlecht
  • Viele Blätter bewegen
  • Fast jeder PK müssen mindestens sein auf einem nicht gruppierten Index
  • Problem geschieht sowohl auf Oracle und SQL Server


Eine mögliche Lösung wird unter Verwendung von Sequential Guid, die erzeugt werden, wie folgt:

    cc6466f7-1066-11dd-acb6-005056c00008
    cc6466f8-1066-11dd-acb6-005056c00008
    cc6466f9-1066-11dd-acb6-005056c00008

Wie sie von C # -Code zu generieren:

[DllImport("rpcrt4.dll", SetLastError = true)]
static extern int UuidCreateSequential(out Guid guid);

public static Guid SequentialGuid()
{
    const int RPC_S_OK = 0;
    Guid g;
    if (UuidCreateSequential(out g) != RPC_S_OK)
        return Guid.NewGuid();
    else
        return g;
}


Vorteile

  • Bessere Nutzung des Index
  • zulassen Verwendung von Cluster-Tasten (sein in NLB-Szenarien überprüft)
  • Weniger Festplattennutzung
  • 20-25% der Leistungssteigerung bei einer minimal Kosten


Das wirkliche Leben Messung: Szenario:

  • GUld als Unique gespeichert Typen auf SQL Server
  • GUID als CHAR gespeichert (36) auf Oracle
  • Lot von Einfügeoperationen, batched zusammen in einer einzigen Transaktion
  • Von 1 bis 100s von Einsätzen je auf dem Tisch
  • Einige Tabellen> 10 Millionen Zeilen


Labortest - SQL Server

VS2008-Test, 10 gleichzeitige Benutzer, keine Denkzeit, Benchmark-Prozess mit 600 Einsätzen in Charge für Blatttabelle
Standard Guid
Durchschn. Prozessdauer: 10.5 sec
Durchschn. Antrag auf zweite: 54,6
Durchschn. Bzw. Zeit: 0,26
Sequential Guid
Durchschn. Prozessdauer: 4.6 sec
Durchschn. Antrag auf zweite: 87,1
Durchschn. Bzw. Zeit: 0,12
Ergebnisse auf Oracle (sorry, anderes Werkzeug für den Test verwendet) 1.327.613 Einsatz auf einen Tisch mit einem Guid PK

Standard Guid , 0,02 sec. verstrichene Zeit für jeden Einsatz, 2.861 sec. die CPU-Zeit, insgesamt 31,049 sec. verstrichene
Sequential Guid , 0,00 sec. verstrichene Zeit für jeden Einsatz, 1.142 sec. die CPU-Zeit, insgesamt 3.667 sec. verstrichene
Die DB-Datei sequentiell gelesen Wartezeit vergangen von 6.4 Millionen warten Ereignisse für 62,415 Sekunden 1.2 Millionen Warten Veranstaltungen für < strong> 11.063 Sekunden.
Es ist wichtig zu sehen, dass alle sequentielle guid erraten werden kann, so ist es keine gute Idee, sie zu benutzen, wenn die Sicherheit ein Anliegen ist, nach wie vor Standard guid verwenden.
Um es kurz zu machen ... wenn Sie Guid verwenden als PK Verwendung sequentieller jedes Mal guid sie nicht hin und her von einem UI weitergegeben werden sie beschleunigen den Betrieb und die kosten nichts zu implementieren.

Andere Tipps

ich hier etwas fehlt möglicherweise (fühlen Sie sich frei, mich zu korrigieren, wenn ich bin), aber ich kann bei der Verwendung sequenzielle GUID / UUID für Primärschlüssel sehr wenig Nutzen sehen.

Die Punkt von GUIDs oder UUIDs über selbstinkrementierende ganze Zahlen verwendet, ist:

  • Sie können überall erstellt werden ohne Kontaktieren der Datenbank
  • Sie sind Kennungen, die in Ihrer Anwendung völlig einzigartig sind (und im Fall von UUIDs, universell eindeutiger)
  • eine Kennung Da gibt es keine Möglichkeit, den nächsten oder vorherige (oder sogar alle andere gültigen Bezeichner), die außerhalb der Brute-Forcing einen großen Schlüsselraumes zu erraten.

Leider Ihren Vorschlag verwenden, verlieren Sie alle diese Dinge.

Also, ja. Sie haben GUIDs besser gemacht. Aber in dem Prozess, haben Sie weggeworfen fast alle der Gründe, sich in erster Linie zu verwenden.

Wenn Sie wirklich will die Leistung verbessern, ein Standard-selbstinkrementierende integer Primärschlüssel verwenden. Das bietet alle Vorteile, die Sie beschrieben (und mehr), während besser zu sein als eine ‚sequentielle guid‘ in fast jeder Hinsicht.

Dies wird höchstwahrscheinlich downmodded in Vergessenheit bekommen, da es nicht speziell Ihre Frage nicht beantworten (die offenbar sorgfältig in Handarbeit gemacht, so dass Sie es sich sofort antworten konnte), aber ich glaube, es ist ein weit wichtiger Punkt zu erhöhen.

Wie massimogentilini bereits gesagt, kann die Leistung verbessert werden, bei der Verwendung von UuidCreateSequential (wenn die GUIDs in Code zu erzeugen). Aber eine Tatsache scheint zu fehlen: Der SQL Server (mindestens Microsoft SQL 2005/2008) die gleiche Funktionalität verwendet, ABER: der Vergleich / Bestellung von Guids unterscheidet sich in .NET und auf dem SQL-Server, die noch mehr IO verursachen würden, weil die guids nicht bestellt richtig werden. Um die guids richtig für SQL Server (Bestellung) bestellt zu erzeugen, müssen Sie Folgendes tun (siehe Vergleich Details):

[System.Runtime.InteropServices.DllImport("rpcrt4.dll", SetLastError = true)]
static extern int UuidCreateSequential(byte[] buffer);

static Guid NewSequentialGuid() {

    byte[] raw = new byte[16];
    if (UuidCreateSequential(raw) != 0)
        throw new System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error());

    byte[] fix = new byte[16];

    // reverse 0..3
    fix[0x0] = raw[0x3];
    fix[0x1] = raw[0x2];
    fix[0x2] = raw[0x1];
    fix[0x3] = raw[0x0];

    // reverse 4 & 5
    fix[0x4] = raw[0x5];
    fix[0x5] = raw[0x4];

    // reverse 6 & 7
    fix[0x6] = raw[0x7];
    fix[0x7] = raw[0x6];

    // all other are unchanged
    fix[0x8] = raw[0x8];
    fix[0x9] = raw[0x9];
    fix[0xA] = raw[0xA];
    fix[0xB] = raw[0xB];
    fix[0xC] = raw[0xC];
    fix[0xD] = raw[0xD];
    fix[0xE] = raw[0xE];
    fix[0xF] = raw[0xF];

    return new Guid(fix);
}

oder Link oder diesen Link .

Wenn Sie Notwendigkeit sequenzielles GUIDs verwenden, SQL Server 2005 können sie für Sie mit der NEWSEQUENTIALID() Funktion erzeugen.

Doch , da die grundlegende Verwendung von GUIDs ist Taste (oder alternative Tasten) zu erzeugen, die nicht erraten werden kann (zum Beispiel Menschen zu vermeiden erraten Schlüssel vorbei auf GETs), ich sehe nicht, wie anwendbar sie sind, weil sie so leicht zu erraten ist.

MSDN :

  

Wichtig:
  Wenn die Privatsphäre ist ein Anliegen, diese Funktion nicht verwenden. Es   ist möglich, den Wert der erraten   nächste erzeugte GUID und daher   Zugangsdaten mit dieser GUID zugeordnet ist.

In diesem Artikel: ( http://www.shirmanov.com/2010/05/generating- NEWSEQUENTIALID-compatible.html )

Auch wenn MSSql verwendet die gleiche Funktion NewSequencialIds zu erzeugen (UuidCreateSequential (aus Guid Guid)), kehrt MSSQL die 3. und 4. Byte-Mustern, die nicht geben Sie das gleiche Ergebnis, das Sie erhalten würden, wenn diese Funktion in Ihrem Code verwenden. Shirmanov zeigt, wie exakt die gleichen Ergebnisse zu erhalten, dass MSSQL schaffen würde.

Schauen Sie sich Kämme von Jimmy Nilsson: eine Art von GUID wo eine Anzahl von Bits wurde mit einem Zeitstempel ähnlichem Wert ersetzt. Dies bedeutet, dass die Kämme bestellt werden können, und wenn sie als Primärschlüssel Ergebnis in weniger Indexseite Splits verwendet, wenn neue Werte eingefügt wird.

Ist es OK, um eine unique~~POS=TRUNC (GUID) als Primärschlüssel zu verwenden?

OK, ich endlich an diesem Punkt in der Konstruktion und Produktion selbst.

I erzeugen eine COMB_GUID wo die oberen 32 Bits, die auf den Bits 33 bis 1 von Unix Zeit in Millisekunden basieren. So gibt es 93 Bits der Zufälligkeit alle 2 Millisekunden und der Überschlag auf dem oberen Bits passieren alle 106 Jahre. Die tatsächliche physikalische Repräsentation des COMB_GUID (oder Typ 4 UUID) ist eine Base64 codierte Version der 128 Bits, was ein 22 char String.

Wenn in Postgres das Verhältnis der Geschwindigkeit zwischen einer vollständig zufälligen UUID und einem Kamms _GUID Einsetzen für die COMB_GUID als vorteilhaft hält. Die COMB_GUID ist 2X schneller auf meiner Hardware über mehrere Tests für eine Million Rekord-Test. Die Aufzeichnungen enthalten die ID (22 Zeichen), ein Zeichenkettenfeld (110 Zeichen), eine doppelte Genauigkeit und ein INT.

In Elasticsearch gibt es keinen erkennbaren Unterschied zwischen den beiden für die Indizierung. Ich werde noch COMB_GUIDS falls Inhalte verwenden geht Indizes irgendwo in der Kette BTree als der Inhalt zugeführt wird zeitbezogene oder kann auf dem ID-Feld vorsortiert werden, so dass es Zeit bezogen und teilweise sequentiell, wird es beschleunigen.

Ziemlich interessant. Der Java-Code machen ein COMB_GUID unten.

import java.util.Arrays;
import java.util.UUID;
import java.util.Base64; //Only avail 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; // makes it every 2 milliseconds
                intFor32bits = (int) time; // rolls over every 106 yers + 1 month from epoch
                babuffer.putInt( 0, intFor32bits);

    }
        //does this cause a memory leak?
        return encoder.encodeToString( babuffer.array() );
    }

}

I messured Unterschied zwischen Guid (gruppierte und nicht gruppierte), Sequential Guid und int (Identität / autoincrement) Entity Framework. Die sequenzielle Guid wurde überraschend schnell im Vergleich zum int mit Identität. Ergebnisse und der Code der sequenzielle Guid hier .

Ich sehe nicht die Notwendigkeit für eindeutige Schlüssel zu erraten oder nicht sein, so dass sie von einem Web-Browser oder in einem anderen Teil vorbei scheint eine schlechte Praxis von selbst und ich sehe nicht ein, wenn Sie Sicherheitsbedenken haben, wie ein mit guid kann die Dinge verbessern (wenn dies die Sache ist, einen echten Zufallszahlengenerator verwenden, um die richtigen Verschlüsselungsfunktionen des Framework).
Die anderen Elemente von meinem Ansatz abgedeckt sind, kann eine sequentielle guid von Code ohne Notwendigkeit für DB-Zugriff (auch wenn es nur für Windows) erzeugt werden, und es ist einzigartig in Zeit und Raum.
Und ja, Frage mit der Absicht, sie zu beantworten, war gestellt Leute zu geben, die Guids für ihre PK einen Weg gewählt hat die Datenbanknutzung zu verbessern (in meinem Fall hat die Kunden erlauben eine wesentlich höhere Arbeitsbelastung zu erhalten, ohne Server zu ändern).
Es scheint, dass Sicherheitsbedenken viel sind, in diesem Fall nicht sequenzielle Guid verwenden oder, besser noch, für PK Standard Guid zu verwenden, die vorwärts und rückwärts von UI und sequentielle guid für alles andere übergeben werden. Wie immer keine absolute Wahrheit gibt, habe ich auch Haupt Antwort bearbeitet, dies zu reflektieren.

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