71 votes

Quelles sont les améliorations de performance de Sequential Guid par rapport à la norme Guid?

Quelqu'un a-t-il déjà mesuré les performances du guidage séquentiel par rapport au guidage standard lorsqu'il est utilisé comme clé primaire dans une base de données?

118voto

massimogentilini Points 2018

GUID vs Séquentielle GUID



Un modèle typique, c'est d'utiliser le Guid que PK pour les tables, mais, comme mentionné dans d'autres discussions (voir http://stackoverflow.com/questions/45399/advantages-and-disadvantages-of-guid-uuid-database-keys) il y a certains problèmes de performances.

C'est typique d'un Guid de la séquence

f3818d69-2552-40b7-a403-01a6db4552f7
7ce31615-fafb-42c4-allée b317-40d21a6a3c60
94732fc7-768e-4cf2-9107-f0953f6795a5


Des problèmes de ce genre de données sont:<
-

  • De larges distributions de valeurs
  • Presque randomically ceux
  • L'utilisation des Index est très, très, très mauvais
  • Beaucoup de feuilles de déménagement
  • Presque tous les PK doivent être au moins sur un index cluster non
  • Le problème se produit à la fois sur Oracle et SQL Server



Une solution possible est l'utilisation Séquentielle Guid, qui sont générés comme suit:

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


Comment générer le code C#:

[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;
}


Avantages

  • Une meilleure utilisation de l'indice de
  • Permettre l'utilisation de clés ordonnées (à vérifié en NLB scénarios)
  • Moins de l'utilisation du disque
  • De 20 à 25% d'augmentation de la performance à un coût minimum



La vie réelle de la mesure: Scénario:

  • Guid stocké comme UniqueIdentifier types sur SQL Server
  • Guid stockées en tant que CHAR(36) sur Oracle
  • Beaucoup d'opérations d'insertion, par lot lors d'une transaction unique
  • De 1 à 100 des inserts en fonction sur la table
  • Quelques tables > 10 millions de lignes



Essai de laboratoire – SQL Server

VS2008 test, 10 utilisateurs simultanés, pas de temps de réflexion, le processus d'analyse comparative avec 600 insère dans le lot par feuille de la table
Standard Guid
Avg. Durée du processus: 10.5sec
Avg. Demande de seconde: 54.6
Avg. Resp. Temps: 0.26

Séquentielle Guid
Avg. Durée du processus: 4.6sec
Avg. Demande de seconde: 87.1
Avg. Resp. Temps: 0.12

Les résultats sur Oracle (désolé, l'outil utilisé pour le test) 1.327.613 insert sur une table avec un Guid PK

Standard Guid, 0.02 sec. temps écoulé pour chaque insertion, 2.861 sec. de temps PROCESSEUR total de 31.049 sec. écoulé

Séquentielle Guid, 0.00 sec. temps écoulé pour chaque insertion, 1.142 sec. de temps PROCESSEUR total de 3.667 sec. écoulé

Le fichier de base de données en lecture séquentielle temps d'attente passé de 6.4 millions d'attente des événements pour 62.415 secondes à 1.2 millions d'attendre les événements pour 11.063secondes.

Il est important de voir que tous les séquentielle guid peut être deviné, il n'est donc pas une bonne idée de les utiliser si la sécurité est une préoccupation, toujours en utilisant la norme de guid.
Pour faire court... si vous utilisez Guid que PK utilisation séquentielle guid chaque fois qu'ils ne sont pas transmises en avant et en arrière à partir d'une INTERFACE utilisateur, ils vont accélérer le fonctionnement et ne coûte rien à mettre en œuvre.

66voto

Dan Points 20968

J'ai peut-être raté quelque chose ici (n'hésitez pas à me corriger si je le suis), mais je vois très peu d'avantages dans l'utilisation séquentielle GUID/Uuid pour les clés primaires.

Le point de l'utilisation de Guid ou Uuid plus autoincrementing entiers est:

  • Ils peuvent être créés n'importe où sans communiquant avec la base de données
  • Ils sont des identifiants qui sont tout à fait unique au sein de votre application (et dans le cas de l'Uuid unique universel)
  • Étant donné un identificateur, il n'y a aucun moyen de deviner la prochaine ou précédente (ou même toutes les autres identificateurs valides) à l'extérieur de brute-forcer un énorme espace.

Malheureusement, à l'aide de votre suggestion, vous perdez toutes ces choses.

Donc, oui. Vous avez fait Guid mieux. Mais dans le processus, vous avez jeté presque toutes les raisons de les utiliser en premier lieu.

Si vous vraiment voulez améliorer les performances, l'utilisation d'un standard autoincrementing integer primary key. Qui offre tous les avantages que vous avez décrit (et plus), tout en étant de mieux qu'un séquentiel guid " dans presque tous les sens.

Ce sera probablement obtenir downmodded dans l'oubli car elle ne permet pas de répondre spécifiquement à votre question (qui, apparemment, est soigneusement conçu de sorte que vous pourriez y répondre vous-même immédiatement), mais je pense que c'est un beaucoup plus point important à soulever.

23voto

Bernhard Kircher Points 1609

Comme massimogentilini déjà dit, les Performances peuvent être améliorées lors de l'utilisation de UuidCreateSequential (lors de la génération du guid dans le code). Mais un fait qui semble manquer: Le Serveur SQL (au moins Microsoft SQL 2005 / 2008) utilise la même fonctionnalité, MAIS: la comparaison/commande de Guid diffèrent .NET et SQL Serveur, ce qui cause encore plus de IO, parce que le guid ne seront pas classés correctement. Afin de générer le guid classés correctement pour sql server (commande), vous devez effectuer les opérations suivantes (voir comparaison de détails):

[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);
}

ou ce lien ou ce lien.

4voto

Sklivvz Points 16412

Si vous avez besoin d'utiliser séquentielle Guid, SQL Server 2005 peut générer pour vous avec l' NEWSEQUENTIALID() fonction.

Cependant , depuis l'utilisation de base de Guid est de générer des clés (ou les touches secondaires) qui ne peut pas être deviné (pour éviter par exemple les gens qui passent à l'aurez deviné touches Obtient), je ne vois pas comment applicable ils sont, car ils sont si faciles à deviner.

À partir de MSDN:

Important:
Si la vie privée est un sujet de préoccupation, n'utilisez pas cette fonction. Il est possible de deviner la valeur de la ensuite généré GUID et, par conséquent, l'accès à des données associées à ce GUID.

4voto

Mitch Wheat Points 169614

Découvrez les Peignes par Jimmy Nilsson: un type de GUID où un certain nombre de bits ont été remplacés par un timestamp comme valeur. Cela signifie que les Peignes peuvent être commandés, et lorsqu'il est utilisé comme clé primaire de moins de fractionnement des pages d'index lors de l'insertion de nouvelles valeurs.

Est-il possible d'utiliser un type uniqueidentifier (GUID) comme Clé Primaire?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X