Je suis après une confirmation de cette idée pour corriger une base de données mal performante ou une meilleure suggestion si quelqu'un en a une. Toujours ouvert à de meilleures suggestions.
J'ai une très grande base de données (plus de 20 millions d'enregistrements augmentant d'environ 1/2 million par jour) qui utilise le GUID comme PK.
Un oubli de ma part mais le PK est clusterisé sur le serveur SQL et cause des problèmes de performances.
La raison d'un GUID - cette base de données est partiellement synchronisée avec 150 autres bases de données, de sorte que le PK devait être unique. La synchronisation n'est pas gérée par SQL Server, il existe plutôt un processus personnalisé construit qui maintient les données synchronisées pour les exigences du système - toutes basées sur ce GUID.
Chacune des 150 bases de données distantes ne stocke pas les données complètes telles qu'elles sont stockées dans la base de données SQL centrale. ils ne stockent qu'un sous-ensemble des données dont ils ont réellement besoin, et les données dont ils ont besoin ne leur sont pas uniques (10 des 150 bases de données peuvent avoir certains des mêmes enregistrements des bases de données d'autres sites par exemple - ils partagent). De plus - les données sont en fait générées sur les sites distants - pas au point central - d'où la nécessité des GUID.
La base de données centrale est utilisée non seulement pour tout synchroniser, mais les requêtes de plus de 3000 utilisateurs seront exécutées sur cette très grande base de données fragmentée. C'est déjà un gros problème lors des tests initiaux.
Heureusement, nous ne sommes pas encore en direct - je peux donc apporter des modifications et mettre les choses hors ligne si nécessaire, ce qui est au moins quelque chose.
Les performances des bases de données distantes ne sont pas un problème - les sous-ensembles de données sont assez petits et la base de données ne dépasse généralement jamais 1 Go au total. Les enregistrements sont renvoyés au système principal assez régulièrement et supprimés des BD plus petits lorsqu'ils ne sont plus nécessaires.
Les performances de la base de données centrale qui est la gardienne de tous les enregistrements sont lamentables - en raison d'un GUID en cluster comme clé primaire pour autant d'enregistrements. La fragmentation de l'indice est hors des graphiques.
Donc - mes réflexions pour résoudre le problème de performances sont de créer une nouvelle colonne - Unsigned BIGINT IDENTITY (1,1), puis de changer le cluster cluster de la colonne BIGINT de la table.
Je créerais un index unique non groupé sur le champ GUID qui était la clé primaire.
Les 150 bases de données distantes plus petites n'ont pas besoin de connaître le nouveau PK sur la base de données Central SQL Server - il sera purement utilisé pour organiser les données dans la base de données et arrêter les mauvaises performances et la fragmentation.
Est-ce que cela fonctionnerait et améliorerait les performances de la base de données SQL centrale et empêcherait un futur enfer de fragmentation d'index (dans une certaine mesure)? ou ai-je raté quelque chose de très important ici qui va me sauter et me mordre et causer encore plus de chagrin?
la source
int
en 4255 jours (11,5 ans). S'il l'a fait, il ne vous en voudrait que dans 11,5 ans;)Réponses:
Vous n'avez certainement pas besoin de cluster sur le GUID. Si vous avez quelque chose qui vous permettrait d'identifier de manière unique des enregistrements autres que ce GUID, je vous suggère de chercher à créer un index unique sur cet autre champ et à rendre cet index en cluster. Sinon, vous êtes libre de regrouper sur d'autres champs, même en utilisant des index non uniques. L'approche qu'il y aurait à regrouper facilite cependant le fractionnement de vos données et l'interrogation - donc, si vous avez un champ "région", ou quelque chose, cela pourrait être un candidat pour votre schéma de clustering.
Le problème avec le passage à a
BIGINT
serait des ajouts aux données d'autres bases de données et l'intégration de leur base de données dans le magasin central. Si ce n'est pas une considération - et ne le sera jamais - alors, oui,BIGINT
cela résoudrait bien le problème de rééquilibrage des indices.En arrière-plan, si vous ne spécifiez pas d'index clusterisé, SQL Server fait à peu près la même chose: il crée un champ d'ID de ligne et mappe tous les autres index dans celui-ci. Donc, en le faisant vous-même, vous le résolvez comme SQL le résoudrait.
la source
C'est un défi de taille.
Permettez-moi de suggérer une approche intermédiaire.
J'avais des problèmes avec System.Guid.NewGuid () générant des guides aléatoires. (Je permettais au client de créer son propre guide, au lieu de s'appuyer sur la base de données pour créer un séquentiel).
Une fois que je suis passé à un UuidCreateSequential côté client, mes performances sont devenues BEAUCOUP meilleures, en particulier sur INSERT.
Voici le code client vaudou de DotNet. Je suis sûr d'avoir mis en gage quelque part:
IDÉE ALTERNATIVE:
Si votre base de données principale et base de données distante sont "liées" (comme dans sp_linkserver) ...... alors vous pouvez utiliser la base de données principale comme "générateur uuid".
Vous ne voulez pas obtenir "un par un" uuid, c'est trop de bavardage.
Mais vous pourriez attraper un ensemble d'uuid.
Ci-dessous est un code:
/ *
* /
la source
En fonction de votre description, optez pour BIGINT. Cependant, l'index du GUID peut être non unique, car les GUID sont censés être globalement uniques de toute façon.
la source
Si le GUID est stocké correctement en tant qu'identificateur unique, il ne devrait pas y avoir de problèmes de performances ... et si vous pouvez utiliser le GUID séquentiel encore mieux ...
@Mattytommo a également un bon point sur 11,5 ans avec l'utilisation de INT ...
la source