Comment enquêter sur les performances d'une instruction BULK INSERT?


12

Je suis principalement un développeur .NET utilisant Entity Framework ORM. Cependant, parce que je ne veux pas échouer dans l'utilisation de l'ORM , j'essaie de comprendre ce qui se passe dans la couche de données (base de données). Fondamentalement, pendant le développement, je démarre le profileur et vérifie ce que certaines parties de code génèrent en termes de requêtes.

Si je repère quelque chose de très compliqué (ORM peut générer des requêtes affreuses même à partir d'instructions LINQ plutôt simples, si elles ne sont pas soigneusement écrites) et / ou lourdes (durée, CPU, lectures de page), je le prends dans SSMS et vérifie son plan d'exécution.

Cela fonctionne bien pour mon niveau de connaissance de la base de données. Cependant, BULK INSERT semble être une créature spéciale, car il ne semble pas produire de SHOWPLAN .

Je vais essayer d'illustrer un exemple très simple:

Définition de table

CREATE TABLE dbo.ImportingSystemFileLoadInfo
(
    ImportingSystemFileLoadInfoId INT NOT NULL IDENTITY(1, 1) CONSTRAINT PK_ImportingSystemFileLoadInfo PRIMARY KEY CLUSTERED,
    EnvironmentId INT NOT NULL CONSTRAINT FK_ImportingSystemFileLoadInfo REFERENCES dbo.Environment,
    ImportingSystemId INT NOT NULL CONSTRAINT FK_ImportingSystemFileLoadInfo_ImportingSystem REFERENCES dbo.ImportingSystem,
    FileName NVARCHAR(64) NOT NULL,
FileImportTime DATETIME2 NOT NULL,
    CONSTRAINT UQ_ImportingSystemImportInfo_EnvXIs_TableName UNIQUE (EnvironmentId, ImportingSystemId, FileName, FileImportTime)
)

Remarque: aucun autre index n'est défini sur la table

L'insert en vrac (ce que j'attrape dans le profileur, un seul lot)

insert bulk [dbo].[ImportingSystemFileLoadInfo] ([EnvironmentId] Int, [ImportingSystemId] Int, [FileName] NVarChar(64) COLLATE Latin1_General_CI_AS, [FileImportTime] DateTime2(7))

Métrique

  • 695 éléments insérés
  • CPU = 31
  • Lit = 4271
  • Écrit = 24
  • Durée = 154
  • Nombre total de tables = 11500

Pour mon application, c'est ok, bien que les lectures semblent assez grandes (je connais très peu de choses sur SQL Server, donc je compare à la taille de page 8K et aux petites informations d'enregistrement que j'ai)

Question: comment puis-je vérifier si cet INSERT EN VRAC peut être optimisé? Ou cela n'a aucun sens, car c'est sans doute le moyen le plus rapide de pousser de grandes données d'une application client vers SQL Server?

Réponses:


14

Pour autant que je sache, vous pouvez optimiser un insert en vrac d'une manière très similaire à celle d'un insert régulier. En règle générale, un plan de requête pour une insertion simple n'est pas très informatif, alors ne vous inquiétez pas de ne pas avoir le plan. Je vais passer en revue quelques façons d'optimiser un insert, mais la plupart d'entre elles ne s'appliquent probablement pas à l'insert que vous avez spécifié dans la question. Cependant, ils pourraient être utiles si à l'avenir vous deviez charger de plus grandes quantités de données.

1. Insérer des données dans l'ordre des clés de clustering

SQL Server trie souvent les données avant de les insérer dans une table avec un index cluster. Pour certaines tables et applications, vous pouvez améliorer les performances en triant les données dans le fichier plat et en indiquant à SQL Server que les données sont triées via l' ORDERargument de BULK INSERT:

COMMANDE ({colonne [ASC | DESC]} [, ... n])

Spécifie comment les données du fichier de données sont triées. Les performances d'importation en masse sont améliorées si les données importées sont triées en fonction de l'index cluster sur la table, le cas échéant.

Puisque vous utilisez une IDENTITYcolonne comme clé en cluster, vous n'avez pas à vous en préoccuper.

2. Utilisez TABLOCKsi possible

Si vous êtes assuré d'avoir une seule session insérant des données dans votre table, vous pouvez spécifier l' TABLOCKargument pour BULK INSERT. Cela peut réduire les conflits de verrous et conduire à une journalisation minimale dans certains scénarios. Cependant, vous insérez dans une table avec un index cluster qui contient déjà des données afin que vous n'obteniez pas une journalisation minimale sans l'indicateur de trace 610 qui est mentionné plus loin dans cette réponse.

Si ce TABLOCKn'est pas possible, parce que vous ne pouvez pas changer le code , tout espoir n'est pas perdu. Pensez à utiliser sp_table_option:

EXEC [sys].[sp_tableoption]
    @TableNamePattern = N'dbo.BulkLoadTable' ,
    @OptionName = 'table lock on bulk load' , 
    @OptionValue = 'ON'

Une autre option consiste à activer l' indicateur de trace 715 .

3. Utilisez une taille de lot appropriée

Parfois, vous pourrez régler les insertions en modifiant la taille du lot.

ROWS_PER_BATCH = row_per_batch

Indique le nombre approximatif de lignes de données dans le fichier de données.

Par défaut, toutes les données du fichier de données sont envoyées au serveur en tant que transaction unique et le nombre de lignes du lot est inconnu de l'optimiseur de requêtes. Si vous spécifiez ROWS_PER_BATCH (avec une valeur> 0), le serveur utilise cette valeur pour optimiser l'opération d'importation en bloc. La valeur spécifiée pour ROWS_PER_BATCH doit être approximativement la même que le nombre réel de lignes. Pour plus d'informations sur les considérations de performances, voir «Remarques», plus loin dans cette rubrique.

Voici la citation de plus tard dans l'article:

Si le nombre de pages à vider dans un même lot dépasse un seuil interne, une analyse complète du pool de mémoire tampon peut se produire pour identifier les pages à vider lorsque le lot est validé. Cette analyse complète peut nuire aux performances d'importation en masse. Un cas probable de dépassement du seuil interne se produit lorsqu'un grand pool de mémoire tampon est combiné avec un sous-système d'E / S lent. Pour éviter les débordements de tampon sur les grandes machines, n'utilisez pas l'indication TABLOCK (qui supprimera les optimisations en bloc) ou utilisez une taille de lot plus petite (qui préserve les optimisations en bloc).

Étant donné que les ordinateurs varient, nous vous recommandons de tester différentes tailles de lots avec votre chargement de données pour savoir ce qui vous convient le mieux.

Personnellement, je voudrais simplement insérer les 695 lignes en un seul lot. Cependant, le réglage de la taille du lot peut faire une grande différence lors de l'insertion de nombreuses données.

4. Assurez-vous que vous avez besoin de la IDENTITYcolonne

Je ne sais rien de votre modèle de données ou de vos exigences, mais ne tombez pas dans le piège d'ajouter une IDENTITYcolonne à chaque table. Aaron Bertrand a un article à ce sujet appelé Bad habitudes to kick: mettre une colonne IDENTITY sur chaque table . Pour être clair, je ne dis pas que vous devez supprimer la IDENTITYcolonne de ce tableau. Cependant, si vous déterminez que la IDENTITYcolonne n'est pas nécessaire et que vous la supprimez, cela pourrait améliorer les performances d'insertion.

5. Désactiver les index ou les contraintes

Si vous chargez une grande quantité de données dans une table par rapport à ce que vous avez déjà, il peut être plus rapide de désactiver les index ou les contraintes avant le chargement et de les activer après le chargement. Pour de grandes quantités de données, il est généralement plus inefficace pour SQL Server de créer un index en une seule fois plutôt que lorsque les données sont chargées dans la table. Il semble que vous ayez inséré 695 lignes dans un tableau avec 11500 lignes, donc je ne recommanderais pas cette technique.

6. Considérez TF 610

L'indicateur de trace 610 permet une journalisation minimale dans certains scénarios supplémentaires. Pour votre table avec une IDENTITYclé en cluster, vous obtiendrez une journalisation minimale pour toutes les nouvelles pages de données tant que votre modèle de récupération est simple ou enregistré en bloc. Je pense que cette fonctionnalité n'est pas activée par défaut car elle peut dégrader les performances sur certains systèmes. Vous devrez tester soigneusement avant d'activer cet indicateur de trace. La référence Microsoft recommandée semble toujours être le Guide de performances de chargement des données

Impact des E / S de la journalisation minimale sous l'indicateur de trace 610

Lorsque vous validez une transaction de chargement en bloc qui a été journalisée de manière minimale, toutes les pages chargées doivent être vidées sur le disque avant la fin de la validation. Toutes les pages vidées non capturées par une opération de point de contrôle antérieure peuvent créer beaucoup d'E / S aléatoires. Comparez cela à une opération entièrement journalisée, qui crée à la place des E / S séquentielles sur les écritures de journal et ne nécessite pas de vidage des pages chargées sur le disque au moment de la validation.

Si votre scénario de chargement consiste en de petites opérations d'insertion sur des btrees qui ne franchissent pas les limites des points de contrôle et que vous avez un système d'E / S lent, l'utilisation d'une journalisation minimale peut en fait ralentir les vitesses d'insertion.

Pour autant que je sache, cela n'a rien à voir avec l'indicateur de trace 610, mais plutôt avec une journalisation minimale elle-même. Je crois que la citation précédente sur le ROWS_PER_BATCHréglage aboutissait à ce même concept.

En conclusion, vous ne pouvez probablement pas faire grand chose pour régler votre BULK INSERT. Je ne serais pas préoccupé par le nombre de lectures que vous avez observé avec votre encart. SQL Server signale les lectures chaque fois que vous insérez des données. Considérez ce qui suit très simplement INSERT:

DROP TABLE IF EXISTS X_TABLE;

CREATE TABLE X_TABLE (
VAL VARCHAR(1000) NOT NULL
);

SET STATISTICS IO, TIME ON;

INSERT INTO X_TABLE WITH (TABLOCK)
SELECT REPLICATE('Z', 1000)
FROM dbo.GetNums(10000); -- generate 10000 rows

Sortie de SET STATISTICS IO, TIME ON:

Tableau 'X_TABLE'. Nombre de balayages 0, lectures logiques 11428

J'ai 11428 rapports lus mais ce ne sont pas des informations exploitables. Parfois, le nombre de lectures signalées peut être réduit par une journalisation minimale, mais bien sûr, la différence ne peut pas être directement traduite en un gain de performances.


12

Je vais commencer à répondre à cette question, avec l'intention de mettre à jour continuellement cette réponse pendant que je construis une base de connaissances de trucs. J'espère que d'autres personnes rencontrent cela et m'aident à améliorer mes propres connaissances au cours du processus.

  1. Gut Check: votre pare-feu effectue-t-il une inspection approfondie et dynamique des paquets? Vous ne trouverez pas grand-chose sur Internet à ce sujet, mais si vos insertions en vrac sont environ 10 fois plus lentes que ce qu'elles devraient être, vous avez probablement un dispositif de sécurité effectuant une inspection approfondie des paquets de niveau 3-7 et vérifiant la "prévention d'injection SQL générique" ".

  2. Mesurez la taille des données que vous prévoyez d'insérer en bloc, en octets, par lot. Et vérifiez si vous stockez des données LOB, car il s'agit d'une opération de récupération et d'écriture de page distincte.

    Plusieurs raisons pour lesquelles vous devriez procéder de cette façon:

    une. Dans AWS, Elastic Block Storage IOPS est décomposé en octets, pas en lignes.

    1. Voir Amazon EBS Volume Performance sur les instances Linux »Caractéristiques et surveillance des E / S pour une explication de ce qu'est une unité EBS IOPS
    2. Plus précisément, les volumes SSD à usage général (gp2) ont le concept de «crédits d'E / S et de performances de rafale» et il est courant que le traitement ETL intensif épuise les crédits de solde de rafales. Votre durée de rafale est mesurée en octets, pas en lignes SQL Server :)

    b. Alors que la plupart des bibliothèques ou des livres blancs testent en fonction du nombre de lignes, c'est vraiment le nombre de pages qui peuvent être écrites à ce sujet, et, pour le calculer, vous devez savoir combien d'octets par ligne et la taille de votre page (généralement 8 Ko) , mais vérifiez toujours si vous avez hérité du système de quelqu'un d'autre.)

    SELECT *
    FROM 
    sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N'YourTable'), NULL, NULL, 'DETAILED')
    

    Faites attention à avg_record_size_in_bytes et page_count.

    c. Comme l'explique Paul White dans https://sqlperformance.com/2019/05/sql-performance/minimal-logging-insert-select-heap , "Pour activer la journalisation minimale avec INSERT...SELECT, SQL Server doit attendre plus de 250 lignes avec une taille totale d'au moins une mesure (8 pages). "

  3. Si vous avez des index avec des contraintes de vérification ou des contraintes uniques, utilisez SET STATISTICS IO ONet SET STATISTICS TIME ON(ou SQL Server Profiler ou SQL Server Extended Events) pour capturer des informations comme si votre insertion en bloc a des opérations de lecture. Les opérations de lecture sont dues au fait que le moteur de base de données SQL Server s'assure que les contraintes d'intégrité passent.

  4. Essayez de créer une base de données de test où le PRIMARYFILEGROUP est monté sur un lecteur RAM. Cela devrait être légèrement plus rapide que le SSD mais aussi éliminer toute question quant à savoir si votre contrôleur RAID pourrait ajouter des frais généraux. En 2018, cela ne devrait pas, mais en créant plusieurs lignes de base différentielles comme celle-ci, vous pouvez avoir une idée générale de la charge supplémentaire que votre matériel ajoute.

  5. Placez également le fichier source sur un lecteur RAM.

    Placer le fichier source sur un lecteur RAM éliminera tout problème de contention si vous lisez le fichier source sur le même lecteur que votre FILEGROUP de serveur de base de données est activé.

  6. Vérifiez que vous avez formaté votre disque dur en utilisant des extensions de 64 Ko.

  7. Utilisez UserBenchmark.com et comparez votre SSD. Cette volonté:

    1. Ajoutez plus de connaissances à d'autres aficionados de la performance sur les performances à attendre d'un appareil
    2. Vous aider à déterminer si les performances de votre lecteur sont inférieures à celles de leurs pairs avec le même lecteur exact
    3. Vous aider à déterminer si les performances de votre disque sont inférieures aux autres disques de la même catégorie (SSD, HDD, etc.)
  8. Si vous appelez "INSERT BULK" à partir de C # via Entity Framework Extensions, assurez-vous de "réchauffer" d'abord le JIT et de "jeter" les premiers résultats.

  9. Essayez de créer des compteurs de performances pour votre programme. Avec .NET, vous pouvez utiliser benchmark.NET et il profilera automatiquement un tas de mesures de base. Vous pouvez ensuite PARTAGER vos tentatives de profilage avec la communauté open source et voir si les personnes exécutant un matériel différent signalent les mêmes mesures (à savoir de mon point précédent sur l'utilisation de UserBenchmark.com pour comparer).

  10. Essayez d'utiliser des canaux nommés et de l'exécuter en tant qu'hôte local.

  11. Si vous ciblez SQL Server et utilisez .NET Core, envisagez de faire tourner un Linux avec SQL Server Std Edition - cela coûte moins d'un dollar par heure, même pour du matériel sérieux. Le principal avantage d'essayer le même code avec le même matériel avec un système d'exploitation différent est de voir si la pile TCP / IP du noyau du système d'exploitation cause des problèmes.

  12. Utilisez les requêtes de diagnostic SQL Server de Glen Barry pour mesurer la latence du lecteur pour le lecteur stockant le FILEGROUP de votre table de base de données.

    une. Assurez-vous de mesurer avant votre test et après votre test. Le "avant votre test" vous indique simplement si vous avez des caractéristiques d'E / S horribles comme base de référence.

    b. Pour mesurer "pendant votre test", vous devez vraiment utiliser les compteurs de performance PerfMon.

    Pourquoi? Parce que la plupart des serveurs de bases de données utilisent une sorte de stockage en réseau (NAS). Dans le cloud, dans AWS, Elastic Block Storage est exactement cela. Vous pourriez être lié par les IOPS de votre solution de volume / NAS EBS.

  13. Utilisez un outil pour mesurer les statistiques d'attente. Red Gate SQL Monitor , SolarWinds Database Performance Analyzer, ou même les requêtes de diagnostic SQL Server de Glen Barry, ou la requête Wait Statistics de Paul Randal .

    une. Les types d'attente les plus courants seront probablement Memory / CPU, WRITELOG, PAGEIOLATCH_EX et ASYNC_NETWORK_IO .

    b. Vous pouvez encourir des types d'attente supplémentaires si vous exécutez des groupes de disponibilité.

  14. Mesurez les effets de plusieurs INSERT BULKcommandes simultanées TABLOCKdésactivées (TABLOCK forcera probablement la sérialisation des commandes INSERT BULK). Votre goulot d'étranglement attend peut-être la fin d'un INSERT BULK; vous devez essayer de mettre en file d'attente autant de tâches que le modèle de données physiques de votre serveur de base de données peut gérer.

  15. Pensez à partitionner votre table. À titre d'exemple particulier: si votre table de base de données est en ajout uniquement, Andrew Novick a suggéré de créer un "AUJOURD'HUI" FILEGROUPet de le partitionner en au moins deux groupes de fichiers, AUJOURD'HUI et BEFORE_TODAY. De cette façon, si vos INSERT BULKdonnées ne sont que des données pour aujourd'hui, vous pouvez filtrer sur un champ CreatedOn pour forcer toutes les insertions à frapper un seul FILEGROUP, et ainsi réduire le blocage lors de l'utilisation TABLOCK. Cette technique est décrite plus en détail dans un livre blanc Microsoft: Stratégies de table et d'index partitionnées à l'aide de SQL Server 2008

  16. Si vous utilisez des index columnstore, désactivez TABLOCKet chargez les données dans 102 400 lignes Taille de lot. Vous pouvez ensuite charger toutes vos données en parallèle directement dans des groupes de lignes columnstore. Cette suggestion (et rationnelle documentée) provient des index Columnstore de Microsoft - Guide de chargement des données :

    Le chargement en bloc a ces optimisations de performances intégrées:

    Charges parallèles: Vous pouvez avoir plusieurs chargements en masse simultanés (bcp ou insertion en bloc) qui chargent chacun un fichier de données distinct. Contrairement aux chargements en bloc de Rowstore dans SQL Server, vous n'avez pas besoin de spécifier TABLOCKcar chaque thread d'importation en bloc chargera les données exclusivement dans des groupes de lignes séparés (groupes de lignes compressés ou delta) avec un verrouillage exclusif. L'utilisation TABLOCKforcera un verrou exclusif sur la table et vous ne pourrez pas importer de données en parallèle.

    Journalisation minimale:Un chargement en masse utilise une journalisation minimale des données qui va directement aux groupes de lignes compressés. Toutes les données qui vont à un groupe de lignes delta sont entièrement enregistrées. Cela inclut toutes les tailles de lot inférieures à 102 400 lignes. Cependant, avec le chargement en masse, l'objectif est que la plupart des données contournent les groupes de lignes delta.

    Optimisation du verrouillage: lors du chargement dans un groupe de lignes compressé, le verrou X sur le groupe de lignes est acquis. Toutefois, lors du chargement en bloc dans le groupe de lignes delta, un verrou X est acquis au niveau du groupe de lignes, mais SQL Server verrouille toujours les verrous PAGE / EXTENT car le verrouillage du groupe de lignes X ne fait pas partie de la hiérarchie de verrouillage.

  17. Depuis SQL Server 2016, il n'est plus nécessaire d'activer l'indicateur de trace 610 pour une connexion minimale à la table indexée . Citant l'ingénieur Microsoft Parikshit Savjani (c'est moi qui souligne ):

    L'un des objectifs de conception de SQL Server 2016 était d'améliorer les performances et l'évolutivité du moteur pour le faire fonctionner plus rapidement sans avoir besoin de boutons ou d'indicateurs de trace pour les clients. Dans le cadre de ces améliorations, l' une des améliorations apportées au code moteur SQL Server était l'activation du contexte de chargement en bloc (également appelé insertions rapides ou contexte de chargement rapide) et la journalisation minimale par défaut lors de l'exécution d'opérations de chargement en bloc sur la base de données avec modèle de récupération enregistré en masse. Si vous n'êtes pas familier avec la journalisation minimale, je vous recommande fortement de lire ce billet de blog de Sunil Agrawal où il explique comment la journalisation minimale fonctionne dans SQL Server. Pour que les insertions en vrac soient enregistrées de manière minimale, elles doivent toujours remplir les conditions préalables qui sont documentées ici.

    Dans le cadre de ces améliorations de SQL Server 2016, vous n'avez plus besoin d'activer l'indicateur de trace 610 pour une connexion minimale à la table indexéeet il rejoint certains des autres drapeaux de trace (1118, 1117, 1236, 8048) pour devenir une partie de l'histoire. Dans SQL Server 2016, lorsque l'opération de chargement en bloc entraîne l'allocation d'une nouvelle page, toutes les lignes remplissant séquentiellement cette nouvelle page sont journalisées de façon minimale si toutes les autres conditions préalables à la journalisation minimale discutées précédemment sont remplies. Les lignes insérées dans les pages existantes (pas de nouvelle allocation de page) pour maintenir l'ordre d'index sont toujours entièrement enregistrées, tout comme les lignes qui sont déplacées à la suite de fractionnements de page pendant le chargement. Il est également important d'avoir ALLOW_PAGE_LOCKS activé pour les index (qui est activé par défaut) pour que l'opération de journalisation minimale fonctionne car les verrous de page sont acquis pendant l'allocation et, par conséquent, seules les allocations de page ou d'étendue sont enregistrées.

  18. Si vous utilisez SqlBulkCopy en C # ou EntityFramework.Extensions (qui utilise SqlBulkCopy sous le capot), vérifiez la configuration de votre build. Exécutez-vous vos tests en mode Release? L'architecture cible est-elle définie sur Any CPU / x64 / x86?

  19. Pensez à utiliser sp_who2 pour voir si la transaction INSERT BULK est SUSPENDUE. Il pourrait être SUSPENDU car il est bloqué par un autre spid. Pensez à lire Comment réduire le blocage de SQL Server . Vous pouvez également utiliser sp_WhoIsActive d'Adam Machanic, mais sp_who2 vous fournira les informations de base dont vous avez besoin.

  20. Vous avez peut-être des E / S de disque défectueuses. Si vous effectuez une insertion en bloc et que votre utilisation du disque n'atteint pas 100% et est bloquée à environ 2%, vous avez probablement soit un mauvais micrologiciel, soit un périphérique d'E / S défectueux. (Cela est arrivé à un de mes collègues.) Utilisez [SSD UserBenchmark] pour comparer avec les autres pour les performances matérielles, surtout si vous pouvez reproduire la lenteur sur votre machine de développement locale. (J'ai mis ce dernier dans la liste car la plupart des entreprises n'autorisent pas les développeurs à exécuter des bases de données sur leur machine locale en raison du risque IP.)

  21. Si votre table utilise la compression, vous pouvez essayer d'exécuter plusieurs sessions, et dans chaque session, commencez par utiliser une transaction existante et exécutez-la avant la commande SqlBulkCopy:

    ALTER SERVER CONFIGURATION SET PROCESS AFFINITY CPU = AUTO;

  22. Pour le chargement continu, un flux d'idées, d'abord décrit dans un livre blanc Microsoft, Stratégies de table et d'index partitionnées à l'aide de SQL Server 2008 :

    Chargement continu

    Dans un scénario OLTP, de nouvelles données peuvent arriver en continu. Si les utilisateurs interrogent également la partition la plus récente, l'insertion de données en continu peut entraîner un blocage: les requêtes des utilisateurs peuvent bloquer les insertions et, de la même manière, les insertions peuvent bloquer les requêtes des utilisateurs.

    Les conflits sur la table ou la partition de chargement peuvent être réduits en utilisant l'isolement de cliché, en particulier le READ COMMITTED SNAPSHOTniveau d'isolement. Sous READ COMMITTED SNAPSHOTisolation, les insertions dans une table ne provoquent pas d'activité dans le magasin de versions tempdb , donc la surcharge de tempdb est minimale pour les insertions, mais aucun verrou partagé ne sera pris par les requêtes des utilisateurs sur la même partition.

    Dans d'autres cas, lorsque des données sont insérées dans une table partitionnée en continu à un taux élevé, vous pouvez toujours être en mesure de mettre en scène les données pendant de courtes périodes dans les tables intermédiaires, puis d'insérer ces données dans la partition la plus récente jusqu'à la fenêtre de la partition actuelle passe et les données sont ensuite insérées dans la partition suivante. Par exemple, supposons que vous ayez deux tables de transfert qui reçoivent chacune 30 secondes de données, sur une base alternative: une table pour la première demi-minute, la deuxième table pour la seconde demi-minute. Une procédure stockée d'insertion détermine dans quelle moitié de la minute l'insertion actuelle se trouve, puis elle s'insère dans la première table de transfert. Lorsque 30 secondes sont écoulées, la procédure d'insertion détermine qu'elle doit s'insérer dans la deuxième table de transfert. Une autre procédure stockée charge ensuite les données de la première table de transfert dans la dernière partition de la table, puis tronque la première table de transfert. Après 30 secondes supplémentaires, la même procédure stockée insère les données de la deuxième procédure stockée et les place dans la partition actuelle, puis tronque la deuxième table de transfert.

  23. Guide de performances de chargement de données de l' équipe Microsoft CAT

  24. Assurez-vous que vos statistiques sont à jour. Utilisez FULLSCAN si vous le pouvez après chaque génération d'index.

  25. Optimisation des performances SAN avec SQLIO et assurez-vous également si vous utilisez des disques mécaniques que vos partitions de disque sont alignées. Voir les meilleures pratiques d'alignement de partition de disque de Microsoft .

  26. COLUMNSTORE INSERT/ UPDATEperformance


2

Les lectures sont susceptibles d'être les contraintes uniques et FK vérifiées pendant l'insertion - vous pouvez obtenir une amélioration de la vitesse si vous pouvez les désactiver / supprimer pendant l'insertion et les activer / recréer ensuite. Vous devrez tester si cela le rend globalement plus lent que de les garder actifs. Cela peut également ne pas être une bonne idée si d'autres processus écrivent simultanément sur la même table. - Gareth Lyons

Selon les questions et réponses, les clés étrangères deviennent non fiables après l'insertion en bloc , les contraintes FK deviennent non fiables après une BULK INSERTsans CHECK_CONSTRAINTSoption (mon cas comme je l'ai terminé avec des contraintes non fiables). Ce n'est pas clair, mais cela n'aurait pas de sens de les vérifier et de les rendre non fiables. Cependant, PK et UNIQUE seront toujours vérifiés (voir BULK INSERT (Transact-SQL) ). - Alexei

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.