Comment augmenter la vitesse de restauration de base de données SQL en utilisant la compression DB et les disques Solid State il ya quelques mois J'ai blogué sur la façon d'accélérer une sauvegarde de base de données complète, mais qu'en est-il la vitesse de restauration En effet également un sujet intéressant à enquêter. Donc, j'ai effectué toutes sortes de tests et j'ai découvert qu'il est possible de restaurer une base de données au moins 3 fois plus rapide à condition que vous disposiez de suffisamment de CPU et de capacité d'E / S disque disponible. Les tests de restauration sont exécutés sur le même matériel que les postes précédents, un serveur 96 Unisys ES7000 avec une unité de stockage à semi-conducteurs DSI 3500 et DSI 3600. La base de données à restaurer est une base de données de 750 Go avec 642 Go de données réparties sur 96 fichiers et 96 groupes de fichiers. Surveillance d'une opération de restauration SQL Server fournit peu d'informations sur la vitesse de restauration lorsqu'une restauration complète de la base de données est en cours, nous pouvons donc compter sur les compteurs réguliers de perfmon de Windows comme 8211 Disk ReadWrite Bytessec pour mesurer le débit 8211 Mean Disk Bytes par ReadWrite pour déterminer l'IO Blockize 8211 Temps processeur du processus SQLServer. Étape 1) La sortie Out of the Box Restauration La première étape consiste à déterminer la bande passante E / S matérielle disponible sur le serveur pour la lecture des fichiers de sauvegarde et la restauration des fichiers de la base de données. Le moyen le plus simple de mesurer cela est d'utiliser l'utilitaire SQLIO. La commande de restauration utilise des E / S étendues allant de 512 Ko à plus de 1 Mo / h (jusqu'à 4), donc laissez le test SQLIO avec de gros blocs également. Le test SQLIO montre que nous disposons d'une largeur de bande de lecture aléatoire disponible de plus de 3 GBytesec et d'une largeur de bande d'écriture aléatoire qui est soutenue sur 2,74 GBsec. Cela devrait être plus que suffisant pour nos expériences de restauration. Étape 2) Création d'une sauvegarde de base de données complète dans un fichier de destination unique Pour sauvegarder la base de données complète avec compression (84267834 pages ou 642 Go) prend 2198 secondes, soit 36 minutes 38 secondes. (Je capture les durées exactes avec SQLProfiler en surveillant la base de données Master). La sauvegarde crée un fichier plat de 317 Go. Impression de la vitesse de sauvegarde: la base de données est lue avec 290 Mo / s et écrit au fichier de destination avec 143 Mo / s. SQLServer utilise environ. 4 CPU: Étape 3) Restauration de la base de données Lecture d'un fichier unique Pour vérifier rapidement le contenu d'un fichier de sauvegarde, vous pouvez utiliser l'interface graphique SSMS ou utiliser la commande suivante: 8212 Pour afficher le contenu d'un jeu de sauvegarde: RESTAURER FILELISTONLY DU DISQUE N8217c : DSI3601LUN01backupTPCH1TBFull1File8217 WITH FILE 1 Avec l'interface utilisateur SSMS ou l'instruction suivante, vous pouvez lancer l'opération Restore: RESTORE DATABASE TPCH1TB À PARTIR DU DISQUE N8217C: DSI3601LUN01BACKUPTPCH1TBFull1File8217 AVEC LE FICHIER 1. NOUNLOAD. REMPLACER. STATS 10 GO Restauration à partir d'un fichier unique Pour restaurer la base de données entière, cela prend 19 minutes et 46 secondes. La restauration de la base de données est beaucoup plus rapide que la sauvegarde (qui a pris 36 min.38 sec.) Les données sont lues à partir du fichier plat avec 1 Moyte IOs et écrite sur SSD avec 512 KB IOs à l'aide 6-7 cœurs J'ai enregistré le disque moyen Écrivez les données de Bytessec dans un journal Perfmon et les compteurs montrent que nous n'atteignons pas une limite matérielle mais le débit d'écriture est une ligne plane régulière qui indique que le débit est limité par l'application elle-même. Temps d'exploration de nos options Restauration Aspects d'optimisation des performances 1 Rédiger le jeu de sauvegarde sur plusieurs fichiers de destination (dispositifs de vidage) accélérera à la fois le processus de sauvegarde et de restauration de manière significative. Pour sauvegarder la base de données à 9 fichiers montre que 84267834 pages sont sauvegardées en 605.411 secondes (1087.430 MBsec). La restauration de la base de données lors de la lecture à partir de 9 fichiers de sauvegarde accélère le processus de restauration, la vitesse d'écriture augmente de façon significative de, en moyenne, 600 Mo à 1479 Mo et se termine en 445.191 secondes avec 18 CPU. C'est 2,5 fois plus rapide. 8211Restore à partir de 9 fichiers avec options RESTORE DATABASE TPCH1TB À PARTIR DU DISQUE N8217c: DSI3601LUN01backupTPCH1TB-Full8217. DISQUE N8217C: DSI3601LUN01backupFile28242. DISQUE N8217C: DSI3601LUN01backupFile38242. DISQUE N8217C: DSI3601LUN00backupFile48242. DISQUE N8217C: DSI3601LUN01backupFile58242. DISQUE N8217c: DSI3601LUN01backupFile68242. DISQUE N8217C: DSI3601LUN01backupFile78242. DISQUE N8217C: DSI3601LUN01backupFile88242. DISQUE N8217C: DSI3601LUN00backupFile98242 AVEC FICHIER 1. NOUNLOAD. REMPLACER. STATS 10 GO Impression de la restauration de l'intégralité du db, lecture à partir de 9 fichiers de sauvegarde: Restauration Performance optimisation tip 2 Pour accélérer le débit encore plus d'expérience avec la spécification de la valeur BUFFERCOUNT. Ceci nous apportera le débit maximum à notre test. Exécution à pleine vitesse la restauration se termine en seulement 5 minutes 40 secondes RESTORE DATABASE a traité avec succès 84267834 pages en 340.330 secondes (1934.423 MBsec). La spécification de la valeur BUFFERCOUNT nous apporte une autre vitesse de restauration supplémentaire de 454 Mo sec DBCC traceon (3605. 3004. 3014. 3213. 8211 1) allez RESTORE DATABASE TPCH1TB DU DISQUE N8217c: DSI3601LUN01backupTPCH1TB-Full8217. DISQUE N8217C: DSI3601LUN01backupFile28242. DISQUE N8217C: DSI3601LUN01backupFile38242. DISQUE N8217C: DSI3601LUN00backupFile48242. DISQUE N8217C: DSI3601LUN01backupFile58242. DISQUE N8217c: DSI3601LUN01backupFile68242. DISQUE N8217C: DSI3601LUN01backupFile78242. DISQUE N8217C: DSI3500LUN01backupFile88242. DISQUE N8217C: DSI3500LUN00backupFile98242 AVEC FICHIER 1. NOUNLOAD. REMPLACER. BUFFERCOUNT 2200 GO DBCC traceoff (3605. 3004. 3014. 3213. 8211 1) GO Impression des différentes mesures tout en restaurant la vitesse maximale: Observations Si vous souhaitez recueillir plus d'informations sur les opérations de sauvegarde et de restauration que vous pouvez activer (dans votre Test environnement uniquement bien sûr), les indicateurs de trace suivants: DBCC traceon (3605, 3004, 3014, 3213, -1). Les informations seront enregistrées dans le journal d'erreurs SQL. Media Set BLOCKSIZE option Pendant les expériences de restauration j'ai remarqué que l'utilisation de l'option Media Set BLOCKSIZE est un tueur sérieux sérieux. Également cette option n'apparaît pas dans le journal J'ai été en supposant que cette option serait en quelque sorte affecter certains des paramètres comme le MinMaxtranferSize mais il doesnt. Avec la BLOCKSIZE mis à 65536, la restauration prend soudainement plus de 8 minutes et le débit d'écriture moyen est inférieur à 1400 MBsec - (avec le paramètre BLOCKSIZE à 32768, la restauration prend plus de 10 minutes pour terminer. Que SQL2005 SP2 est capable d'écrire des E / S de 1 Mo / s pendant les opérations de restauration afin de réduire les besoins d'extension de fichier et la maintenance des métadonnées NTFS. L'augmentation de l'option MAXTRANSFERSIZE semble affecter la taille du bloc d'écriture IO, elle augmente de 600-800 Ko à 1Mb Ou plus, mais pendant mes expériences, le kilométrage variait. Sampler le sys. dmoswaitstats SQL pendant 20 secondes: BACKUPIO: Se produit lorsqu'une tâche de sauvegarde attend des données ou attend un tampon dans lequel stocker des données: malheureusement, augmenter encore le buffercount Ne contribue pas à réduire ce nombre d'attente 1. L'ajout de plusieurs LUN aidera à résoudre le problème. Très grand 4-5 MByte écrit: Restauration sur un niveau File ou FileGroup Outre l'option de restauration complète de base de données, vous pouvez également restaurer sur un File - ou FileGroup base. J'ai couru quelques tests pour voir si ces options vont restaurer encore plus vite. Restaurer un seul groupe de fichiers Pour restaurer un seul groupe de fichiers (6,7 Go 877928 pages) prend 7 minutes et 7 secondes (17,3 Mo). Avec Buffercount1100 spécifié il prend seulement 3 minutes 12 secondes (41,2 MBsec). Une seule restauration FileGroup utilise jusqu'à 17 CPU, ce qui ne serait pas une option pour restaurer plusieurs FileGroups en parallèle pour accélérer l'opération de restauration. Également parce que vous ne pouvez pas démarrer 2 tâches de restauration FG en parallèle: Lorsque vous démarrez plusieurs tâches de restauration FileGroup vous recevez le message L'accès exclusif n'a pas pu être obtenu parce que la base de données est en cours d'utilisation. Restaurer tous en séquence 1 par 1 aurait pris près de 5 heures. Mais vous pouvez spécifier Tous les groupes de fichiers pour les restaurer tous à la fois. La restauration de tous les 97 groupes de fichiers (y compris le serveur principal) offre des performances similaires à celles d'une restauration complète de base de données complète: meilleur résultat. 5 minutes 39 secondes. (RESTORE DATABASE 8230 FILEltnamegt a traité avec succès 84267834 pages en 339.174 secondes (1941.016 MBsec)). Vous pouvez ensuite vérifier l'état du groupe de fichiers à l'aide de la commande suivante: SELECT name, saidesc FROM sys. databasefiles Si vous avez oublié de restaurer un ou plusieurs Filegroups, le statut Statedesc sera RESTORING au lieu de ONLINE. Les astuces pour accélérer une sauvegarde de base de données s'appliquent également pour augmenter la vitesse de restauration simplement ajouter plus de fichiers de destination de sauvegarde et spécifier une valeur Buffercount élevée. Cela vous amènera à des restaurations 3.3x plus rapide. Dans mes tests, le temps de restauration d'une base de données de 462 Go a diminué d'environ 20 minutes à moins de 6 minutes. Si vous disposez de CPU suffisantes (en moyenne 23, jusqu'à 34 CPU sont utilisées par SQLServer) et le stockage en état solide rapide pour suivre le débit IO, SQL Server 2008R2 tirera parti des CPU et de la largeur de bande IO disponibles pour restaurer rapidement les bases de données . Comment augmenter la vitesse de restauration de la base de données SQL en utilisant la compression DB et Solid State Disks. 5.0 out of 5 based on 14 ratingsLa plupart des gens sont familiers avec la phrase, quotthis tuera deux oiseaux avec un stonequot. Si vous ne le faites pas, la phase se réfère à une approche qui aborde deux objectifs dans une action. (Malheureusement, l'expression elle-même est plutôt désagréable, car la plupart d'entre nous ne veulent pas jeter des pierres à des animaux innocents). Aujourd'hui, je vais couvrir quelques notions de base sur deux grandes fonctionnalités de SQL Server: l'index Columnstore (disponible uniquement dans SQL Server Enterprise) Le magasin de requêtes SQL. Microsoft a effectivement implémenté l'index Columnstore dans SQL 2012 Enterprise, bien qu'ils l'aient amélioré dans les deux dernières versions de SQL Server. Microsoft a introduit Query Store dans SQL Server 2016. Alors, quelles sont ces fonctionnalités et pourquoi sont-elles importantes? Bien, j'ai une démo qui présentera les deux fonctionnalités et montrera comment elles peuvent nous aider. Avant d'aller plus loin, je traite également de ce (et d'autres fonctionnalités SQL 2016) dans mon article CODE Magazine sur les nouvelles fonctionnalités SQL 2016. Comme introduction de base, l'index Columnstore peut aider à accélérer les requêtes qui scanaggregate sur de grandes quantités de données et Le magasin de requêtes suit les exécutions de requêtes, les plans d'exécution et les statistiques d'exécution que vous devez habituellement collecter manuellement. Croyez-moi quand je dis, ce sont de grandes caractéristiques. Pour cette démo, j'utiliserai la base de données de démonstration Microsoft Contoso Retail Data Warehouse. Franchement parler, Contoso DW est comme quota vraiment grand AdventureWorksquot, avec des tables contenant des millions de lignes. (La plus grande table d'AdventureWorks contient environ 100 000 lignes au maximum). Vous pouvez télécharger la base de données Contoso DW ici: microsoften-usdownloaddetails. aspxid18279. Contoso DW fonctionne très bien lorsque vous souhaitez tester les performances sur les requêtes sur des tables plus grandes. Contoso DW contient une table de données d'entrepôt de données standard appelée FactOnLineSales, avec 12,6 millions de lignes. Ce n'est certainement pas la plus grande table d'entrepôt de données au monde, mais elle ne joue pas non plus. Supposez que je veux résumer le montant des ventes de produits pour 2009 et classer les produits. Je pourrais interroger la table de faits et joindre à la table de dimension de produit et utiliser une fonction RANK, comme suit: Here39s un ensemble de résultat partiel des 10 rangées supérieures, par les ventes totales. Sur mon ordinateur portable (i7, 16 Go de RAM), la requête prend de 3-4 secondes à s'exécuter. Cela pourrait ne pas sembler la fin du monde, mais certains utilisateurs pourraient s'attendre à des résultats presque instantanés (la façon dont vous pourriez voir des résultats presque instantanés lors de l'utilisation d'Excel contre un cube OLAP). Le seul index que j'ai actuellement sur cette table est un index clusterisé sur une clé de ventes. Si je regarde le plan d'exécution, SQL Server propose une suggestion pour ajouter un index couvrant à la table: Maintenant, juste parce que SQL Server suggère un index, doesn39t signifie que vous devez aveuglément créer des index sur chaque quotmissing indexquot message. Toutefois, dans ce cas, SQL Server détecte que nous filtrons en fonction de l'année et en utilisant la clé de produit et le montant des ventes. Ainsi, SQL Server suggère un indice couvrant, avec la DateKey comme le champ de clé d'index. La raison pour laquelle nous appelons cela un quotcoveringquot index est parce que SQL Server quotbring le long des champs non-clé nous avons utilisé dans la requête, quotfor the ridequot. De cette façon, SQL Server n'a pas besoin d'utiliser la table ou l'index clusterisé à tout le moteur de base de données peut simplement utiliser l'index couvrant pour la requête. Les index de couverture sont populaires dans certains scénarios de base de données et d'entreposage de données, bien qu'ils aient un coût de maintenance du moteur de base de données. Remarque: Les index de couverture existent depuis longtemps, donc je n'ai pas encore couvert l'index Columnstore et le magasin de requêtes. Donc, je vais ajouter l'indice de couverture: Si je re-exécuter la même requête que j'ai couru il ya un moment (celle qui a agrégé le montant des ventes pour chaque produit), la requête semble parfois exécuter environ une seconde plus rapide, et je reçois un Plan d'exécution différent, qui utilise une recherche d'index au lieu d'une analyse d'index (en utilisant la clé de date sur l'index couvrant pour récupérer les ventes pour 2009). Ainsi, avant l'index Columnstore, cela pourrait être une façon d'optimiser cette requête dans les versions beaucoup plus anciennes de SQL Server. Il fonctionne un peu plus vite que le premier, et je reçois un plan d'exécution avec un Index Seek au lieu d'un Index Scan. Cependant, il y a quelques problèmes: Les deux opérateurs d'exécution quotIndex Seekquot et quotHash Match (Aggregate) quot fonctionnent essentiellement quotrow par rowquot. Imaginez cela dans une table avec des centaines de millions de lignes. En relation, pensez au contenu d'une table de faits: dans ce cas, une seule valeur de clé de date et / ou une valeur de clé de produit unique peuvent être répétées à travers des centaines de milliers de lignes (rappelez-vous, la table de faits a également des clés pour la géographie, la promotion, le vendeur , Etc.). Ainsi, lorsque le quotIndex Seekquot et le quotHash Matchquot travaillent ligne par ligne, ils le font sur des valeurs qui peuvent être répétées à travers plusieurs autres lignes. C'est normalement là où I39d suit à l'index Columnstore de SQL Server, qui offre un scénario pour améliorer la performance de cette requête de manière étonnante. Mais avant de le faire, retournons dans le temps. Let's revenir à l'année 2010, lorsque Microsoft a introduit un add-in pour Excel connu sous le nom PowerPivot. Beaucoup de gens se souviennent probablement avoir vu des démos de PowerPivot pour Excel, où un utilisateur pouvait lire des millions de lignes d'une source de données externe dans Excel. PowerPivot compresserait les données et fournirait un moteur pour créer des tableaux croisés et des tableaux croisés qui fonctionnaient à des vitesses étonnantes par rapport aux données compressées. PowerPivot a utilisé une technologie en mémoire que Microsoft a appelée quotVertiPaqquot. Cette technologie en mémoire dans PowerPivot prendrait essentiellement dupliquer les clés clés d'entreprise et les compresser vers un seul vecteur. La technologie en mémoire analyserait également ces valeurs en parallèle, en blocs de plusieurs centaines à la fois. Le résultat final est que Microsoft a cuit une grande quantité d'améliorations de la performance dans la fonction en mémoire de VertiPaq pour que nous puissions l'utiliser, à droite de la boîte proverbiale. Pourquoi est-ce que je prends cette petite promenade en bas de la voie de mémoire Puisque dans SQL Server 2012, Microsoft a implémenté une des caractéristiques les plus importantes dans l'histoire de leur moteur de base de données: l'index de Columnstore. L'index est vraiment un index dans le nom uniquement: c'est un moyen de prendre une table SQL Server et de créer un compressed, en colonne columnstore qui compresse les valeurs de clé étrangère en double jusqu'à valeurs vectorielles simples. Microsoft a également créé un nouveau pool de mémoire tampon pour lire ces valeurs vectorielles compressées en parallèle, créant ainsi le potentiel d'énormes gains de performance. Ainsi, je vais créer un index de colonne sur la table, et je verrai combien mieux (et plus efficacement) la requête s'exécute, par rapport à la requête qui s'exécute contre l'indice de couverture. Ainsi, je créerai une copie de FactOnlineSales (I39ll l'appeler FactOnlineSalesDetailNCCS), et I39ll créeront un index de columnstore sur la table dupliquée de cette façon que je won39t interférer avec la table originale et l'indice couvrant en aucune façon. Ensuite, je créerai un index de colonne sur la nouvelle table: Notez plusieurs choses: J'ai spécifié plusieurs colonnes de clés étrangères, ainsi que le montant des ventes. N'oubliez pas qu'un index columnstore n'est pas comme un index traditionnel de magasin en ligne. Il n'y a pas de quotkeyquot. Nous indiquons simplement quelles colonnes SQL Server doit compresser et placer dans un magasin de colonnes en mémoire. Pour utiliser l'analogie de PowerPivot pour Excel lors de la création d'un index de colonne, nous demandons à SQL Server de faire essentiellement la même chose que PowerPivot lorsque nous avons importé 20 millions de lignes dans Excel à l'aide de PowerPivot. La table duplicée FactOnlineSalesDetailNCCS qui contient l'index columnstore. Cette requête s'exécute instantanément en moins d'une seconde. Et je peux aussi dire que même si la table avait des centaines de millions de rangées, il serait toujours courir à la quotbat proverbiale d'un cils. Nous pourrions examiner le plan d'exécution (et dans quelques instants, nous le ferons), mais maintenant il est temps de couvrir la fonctionnalité de magasin de requêtes. Imaginez un instant que nous avons exécuté les deux requêtes du jour au lendemain: la requête qui utilisait la table régulière FactOnlineSales (avec l'index de couverture), puis la requête qui utilisait la table dupliquée avec l'index Columnstore. Lorsque nous nous connectons le lendemain matin, nous aimerions voir le plan d'exécution pour les deux requêtes telles qu'elles ont eu lieu, ainsi que les statistiques d'exécution. En d'autres termes, nous aimerions voir les mêmes statistiques que nous pourrions voir si nous avons exécuté les deux requêtes interactivement dans SQL Management Studio, tourné dans TIME et IO Statistics, et vu le plan d'exécution juste après l'exécution de la requête. Eh bien, c'est ce que le magasin de requêtes nous permet de faire, nous pouvons activer (activer) Query Store pour une base de données, qui va déclencher SQL Server pour stocker l'exécution de la requête et planifier les statistiques afin que nous puissions les afficher plus tard. Donc, je vais activer le magasin de requêtes sur la base de données Contoso avec la commande suivante (et I39ll également effacer toute mise en cache): Puis I39ll exécuter les deux requêtes (et quotpretendquot que je les ai exécuté il ya quelques heures): Maintenant, depuis. Selon ce que j'ai dit, le Query Store va capturer les statistiques d'exécution. Alors, comment puis-je les voir Heureusement, c'est très facile. Si je développe la base de données Contoso DW, je verrai un dossier Query Store. Le Query Store a une fonctionnalité énorme et I39ll essayer de couvrir une grande partie de celui-ci dans les posts suivants. Mais pour le moment, je veux voir les statistiques d'exécution sur les deux requêtes, et examiner spécifiquement les opérateurs d'exécution pour l'index columnstore. Alors, cliquez avec le bouton droit de la souris sur les Requêtes de consommations de ressources principales et exécutez cette option. Cela me donne un graphique comme celui ci-dessous, où je peux voir la durée d'exécution (en millisecondes) pour toutes les requêtes qui ont été exécutées. Dans ce cas, la requête 1 était la requête par rapport à la table d'origine avec l'index de recouvrement et la requête 2 était contre la table avec l'index de la colonne. Les nombres ne sont pas l'indice columnstore surperformed l'indice initial tablecovering index par un facteur de presque 7 à 1. Je peux changer la métrique pour regarder la consommation de mémoire à la place. Dans ce cas, notez que la requête 2 (la requête d'index de colonne) a utilisé beaucoup plus de mémoire. Cela démontre clairement pourquoi l'index columnstore représente la technologie quotin-memoryquot. SQL Server charge l'index columnstore entier en mémoire et utilise un pool de mémoire tampon complètement différent avec des opérateurs d'exécution améliorés pour traiter l'index. Si vous cliquez sur la barre verticale pour la requête qui a utilisé l'index columnstore, vous verrez l'exécution Plan ci-dessous. La première chose que nous voyons est que SQL Server a effectué un scan d'index colonne, et qui représentait près de 100 du coût de la requête. Vous pourriez dire, quotEt attendre une minute, la première requête a utilisé un indice couvrant et a effectué une recherche d'indice ainsi comment peut-être une analyse d'index colonne est plus rapide. C'est une question légitime, et heureusement il y a une réponse. Même lorsque la première requête a effectué une recherche d'index, elle a toujours exécuté quotrow par rowquot. Si je passe la souris sur l'opérateur scan de l'index colonne, je vois une info-bulle (comme celle ci-dessous), avec un paramètre important: le mode d'exécution est BATCH (par opposition à ROW. Indice de couverture). Ce mode BATCH nous indique que SQL Server traite les vecteurs compressés (pour toutes les valeurs de clés étrangères qui sont dupliquées, telles que la clé de produit et la clé de date) dans des lots de près de 1000, en parallèle. Ainsi, SQL Server est toujours en mesure de traiter l'index columnstore beaucoup plus efficacement. De plus, si je place la souris sur la tâche Hash Match (Agrégat), je vois également que SQL Server agrège l'index columnstore en mode Batch (bien que l'opérateur lui-même représente un si petit pourcentage du coût de la requête) SQL Server compresse les valeurs dans les données, traite les valeurs en tant que vecteurs et les lit dans des blocs de près de mille valeurs en parallèle, mais ma requête ne voulait que des données pour 2009. Ainsi, SQL Server scanne Ensemble de données Une fois de plus, une bonne question. La réponse est, quotNot reallyquot. Heureusement pour nous, le nouveau pool de mémoire tampon d'index columnstore exécute une autre fonction appelée quotsegment eliminationquot. Basiquement, SQL Server examinera les valeurs vectorielles de la colonne de la clé de date dans l'index de la colonne et éliminera les segments qui ne sont pas dans la portée de l'année 2009. I39ll s'arrêtera ici. Dans les articles de blog suivants, I39ll couvre l'index columnstore et Query Store en détail. Essentiellement, ce que nous avons vu ici aujourd'hui est que l'index Columnstore peut considérablement accélérer les requêtes qui scanaggregate sur de grandes quantités de données, et le Query Store capture les exécutions de requête et nous permettent d'examiner les statistiques d'exécution et de performance plus tard. En fin de compte, nous aimerions produire un jeu de résultats qui montre ce qui suit. Notez trois choses: Les colonnes pivotent essentiellement toutes les raisons de retour possibles, après avoir indiqué le montant des ventes Le jeu de résultats contient des sous-totaux par la date de fin de semaine (dimanche) sur tous les clients (où le client est NULL) Ligne (où le client et la date sont tous les deux NULL) Tout d'abord, avant que j'obtienne dans la fin de SQL nous pourrions employer la capacité dynamique de pivotmatrix dans SSRS. Nous aurions simplement besoin de combiner les deux ensembles de résultats par une colonne et ensuite nous pourrions alimenter les résultats au contrôle matriciel SSRS, qui répartira les raisons de retour sur l'axe des colonnes du rapport. Cependant, tout le monde n'utilise pas SSRS (bien que la plupart des gens devraient). Mais même alors, parfois les développeurs ont besoin de consommer des ensembles de résultats dans autre chose qu'un outil de reporting. Donc, pour cet exemple, supposons que nous voulons générer le jeu de résultats pour une page de grille Web et éventuellement le développeur veut quotstrip outquot les lignes de sous-total (où j'ai une valeur ResultSetNum de 2 et 3) et les placer dans une grille de synthèse. Donc bottom line, nous devons générer la sortie ci-dessus directement à partir d'une procédure stockée. Et comme un twist ajouté la semaine prochaine il pourrait y avoir Retour Raison X et Y et Z. Donc nous don39t savoir combien de raisons de retour il pourrait y avoir. Nous voulons simplement que la requête pivote sur les valeurs distinctes possibles pour la Raison de retour. Voici où le T-SQL PIVOT a une restriction, nous devons lui fournir les valeurs possibles. Puisque nous ne savons pas que jusqu'à l'exécution, nous devons générer la chaîne de requête dynamiquement en utilisant le modèle SQL dynamique. Le pattern SQL dynamique implique de générer la syntaxe, pièce par pièce, de le stocker dans une chaîne, puis d'exécuter la chaîne à la fin. Dynamic SQL peut être délicat, car nous devons intégrer la syntaxe dans une chaîne. Mais dans ce cas, c'est notre seule option vraie si nous voulons gérer un nombre variable de raisons de retour. J'ai toujours trouvé que la meilleure façon de créer une solution SQL dynamique est de déterminer ce que le quotidealquot généré-interrogation serait à la fin (dans ce cas, étant donné les raisons de retour que nous connaissons) et puis l'ingénierie inverse en piecing Ensemble une partie à la fois. Et donc, voici le SQL dont nous avons besoin si nous savions que les raisons de retour (A à D) étaient statiques et ne changeraient pas. La requête fait ce qui suit: Combine les données de SalesData avec les données de ReturnData, où nous quothard-wire le mot Sales comme un type d'action de la table Sales, puis utiliser la raison de retour des données de retour dans la même colonne ActionType. Cela nous donnera une colonne ActionType propre sur laquelle pivoter. Nous combinons les deux instructions SELECT dans une expression de table commune (CTE), qui est fondamentalement une sous-requête de table dérivée que nous utilisons par la suite dans l'instruction suivante (à PIVOT) Une instruction PIVOT contre le CTE, qui somme les dollars pour le Type d'Action Étant dans l'une des valeurs de type d'action possibles. Notez que ce n'est pas le résultat final. Nous plaçons cela dans un CTE qui se lit du premier CTE. La raison en est que nous voulons faire plusieurs regroupements à la fin. L'instruction SELECT finale, qui lit à partir du PIVOTCTE et la combine avec une requête ultérieure sur le même PIVOTCTE, mais où nous mettons en œuvre deux regroupements dans la fonctionnalité GROUPING SETS dans SQL 2008: GROUPING par la date de fin de semaine (dbo. WeekEndingDate) GROUPAGE pour toutes les lignes () Donc, si nous savions avec certitude que nous n'aurions jamais plus de codes de raison de retour, alors ce serait la solution. Cependant, nous devons tenir compte d'autres codes de raison. Donc nous devons générer cette requête entière au-dessus comme une grande chaîne où nous construisons les raisons de retour possibles comme une liste séparée par des virgules. I39m va montrer l'ensemble du code T-SQL pour générer (et exécuter) la requête désirée. Et puis je le diviserai en parties et expliquerai chaque pas. Donc d'abord, voici le code entier pour générer dynamiquement ce que j'ai obtenu ci-dessus. Il ya essentiellement cinq étapes que nous devons couvrir. Étape 1 . Nous savons que quelque part dans le mixage, nous devons générer une chaîne pour cela dans la requête: SalesAmount, Raison A, Raison B, Raison C, Raison D0160016001600160 Ce que nous pouvons faire est construit une expression de table commune temporaire qui combine les quot Colonne avec la liste unique des codes de raison possible. Une fois que nous avons cela dans un CTE, nous pouvons utiliser le petit truc de FOR XML PATH (3939) pour réduire ces lignes en une seule chaîne, mettre une virgule devant chaque ligne que la requête lit, puis utiliser STUFF pour remplacer La première instance d'une virgule avec un espace vide. C'est un truc que vous pouvez trouver dans des centaines de blogs SQL. Donc, cette première partie construit une chaîne appelée ActionString que nous pouvons utiliser plus bas. Étape 2 . Nous savons aussi que nous souhaitons SOMME les colonnes de raison générées générées, ainsi que la colonne de vente standard. Nous aurons donc besoin d'une chaîne séparée pour cela, appelée SUMSTRING. I39ll utiliser simplement l'ActionString d'origine, puis REMPLACER les parenthèses externes avec la syntaxe SUM, plus les parenthèses d'origine. Étape 3: Maintenant le véritable travail commence. En utilisant cette requête originale en tant que modèle, nous voulons générer la requête originale (en commençant par l'UNION des deux tables), mais en remplaçant toute référence aux colonnes pivotées par les chaînes générées dynamiquement ci-dessus. De plus, bien que ce ne soit pas absolument nécessaire, nous avons également créé une variable pour tout simplement les combinaisons de flux de chariot à retourner que nous voulons intégrer dans la requête générée (pour la lisibilité). So we39ll construire la requête entière dans une variable appelée SQLPivotQuery. Étape 4 . Nous continuons à construire la requête à nouveau, en concaténant la syntaxe que nous pouvons quothard-wirequot avec l'ActionSelectString (que nous avons généré dynamiquement pour contenir toutes les valeurs de raison de retour possible) Étape 5. Enfin, nous générons la partie finale de la requête Pivot, qui lit à partir de la 2ème expression de table commune (PIVOTCTE, du modèle ci-dessus) et génère la SELECT finale à lire de la PIVOTCTE et la combine avec une 2ème lecture contre PIVOTCTE Mettre en œuvre les ensembles de regroupement. Enfin, nous pouvons citerexécuter la chaîne à l'aide du système SQL stocké proc spexecuteSQL Donc j'espère que vous pouvez voir que le processus à suivre pour ce type d'effort est Déterminer ce que la requête finale serait, en fonction de votre ensemble actuel de données et valeurs Un modèle de requête) Rédigez le code T-SQL nécessaire pour générer ce modèle de requête sous forme de chaîne. Peut-être la partie la plus importante est de déterminer l'ensemble unique de valeurs sur lesquelles youll PIVOT, puis de les effondrer en une seule chaîne à l'aide de la fonction STUFF et la trame FOR XML PATH (3939) Donc ce qui est dans mon esprit aujourd'hui Eh bien, au moins 13 articles Deux Il ya quelques années, j'ai écrit un projet de BDR qui a mis l'accent (en partie) sur le rôle de l'éducation et la valeur d'un bon art des arts libéraux non seulement pour l'industrie du logiciel, mais même pour d'autres industries ainsi. Un des thèmes de ce BDR particulier a souligné un point de vue pivot et éclairé de l'architecte de logiciel de renommée Allen Holub concernant les arts libéraux. Illustrant fidèlement son message: il met en évidence les parallèles entre la programmation et l'étude de l'histoire, en rappelant à tout le monde que l'histoire est la lecture et l'écriture, et le développement logiciel est aussi la lecture et l'écriture ). Et donc j'ai écrit un article d'opinion qui s'est concentré sur ceci et d'autres sujets connexes. Mais jusqu'à aujourd'hui, je n'ai jamais eu le temps de publier. De temps en temps, je pense à la réviser, et je me suis même asseoir pendant quelques minutes et faire quelques ajustements. Mais alors la vie en général obtiendrait dans la manière et l'Id ne finira jamais. Donc, ce qui a changé Il ya quelques semaines, collègues chroniqueur CoDe Magazine et leader de l'industrie Ted Neward a écrit un morceau dans sa colonne régulière, Managed Coder, qui a attiré mon attention. Le titre de l'article est On Liberal Arts. Et je recommande fortement que tout le monde le lire. Ted discute de la valeur d'un milieu des arts libéraux, de la fausse dichotomie entre les arts libéraux et le succès dans le développement de logiciels, et la nécessité de bien communiquer. Il parle de certaines de ses propres rencontres passées avec la gestion du personnel RH en ce qui concerne ses études. Il souligne également la nécessité d'accepter et de s'adapter aux changements dans notre industrie, ainsi que les caractéristiques d'un logiciel professionnel réussi (être fiable, planifier à l'avance et apprendre à passer le conflit initial avec les autres membres de l'équipe). Donc c'est une grande lecture, tout comme Teds d'autres articles CoDe et entrées de blog. Cela m'a également permis de réfléchir à mes points de vue à ce sujet (et à d'autres sujets), et finalement m'a motivé à terminer mon propre éditorial. Donc, mieux vaut tard que jamais, voici mes boulangers actuels Douzaine de réflexions: J'ai un dicton: L'eau gèle à 32 degrés. If youre in a trainingmentoring role, you might think youre doing everything in the world to help someone when in fact, theyre only feeling a temperature of 34 degrees and therefore things arent solidifying for them. Sometimes it takes just a little bit more effort or another ideachemical catalyst or a new perspective which means those with prior education can draw on different sources. Water freezes at 32 degrees . Some people can maintain high levels of concentration even with a room full of noisy people. Im not one of them occasionally I need some privacy to think through a critical issue. Some people describe this as you gotta learn to walk away from it. Stated another way, its a search for the rarefied air. This past week I spent hours in half-lit, quiet room with a whiteboard, until I fully understood a problem. It was only then that I could go talk with other developers about a solution. The message here isnt to preach how you should go about your business of solving problems but rather for everyone to know their strengths and what works, and use them to your advantage as much as possible. Some phrases are like fingernails on a chalkboard for me. Use it as a teaching moment is one. (Why is it like fingernails on a chalkboard Because if youre in a mentoring role, you should usually be in teaching moment mode anyway, however subtly). Heres another I cant really explain it in words, but I understand it. This might sound a bit cold, but if a person truly cant explain something in words, maybe they dont understand. Sure, a person can have a fuzzy sense of how something works I can bluff my way through describing how a digital camera works but the truth is that I dont really understand it all that well. There is a field of study known as epistemology (the study of knowledge). One of the fundamental bases of understanding whether its a camera or a design pattern - is the ability to establish context, to identify the chain of related events, the attributes of any components along the way, etc. Yes, understanding is sometimes very hard work, but diving into a topic and breaking it apart is worth the effort. Even those who eschew certification will acknowledge that the process of studying for certification tests will help to fill gaps in knowledge. A database manager is more likely to hire a database developer who can speak extemporaneously (and effortlessly) about transaction isolation levels and triggers, as opposed to someone who sort of knows about it but struggles to describe their usage. Theres another corollary here. Ted Neward recommends that developers take up public speaking, blogging, etc. I agree 100. The process of public speaking and blogging will practically force you to start thinking about topics and breaking down definitions that you might have otherwise taken for granted. A few years ago I thought I understood the T-SQL MERGE statement pretty well. But only after writing about it, speaking about, fielding questions from others who had perspectives that never occurred to me that my level of understanding increased exponentially. I know a story of a hiring manager who once interviewed an authordeveloper for a contract position. The hiring manager was contemptuous of publications in general, and barked at the applicant, So, if youre going to work here, would you rather be writing books or writing code Yes, Ill grant that in any industry there will be a few pure academics. But what the hiring manager missed was the opportunities for strengthening and sharpening skill sets. While cleaning out an old box of books, I came across a treasure from the 1980s: Programmers at Work. which contains interviews with a very young Bill Gates, Ray Ozzie, and other well-known names. Every interview and every insight is worth the price of the book. In my view, the most interesting interview was with Butler Lampson. who gave some powerful advice. To hell with computer literacy. Its absolutely ridiculous. Study mathematics. Learn to think. Read. Write. These things are of more enduring value. Learn how to prove theorems: A lot of evidence has accumulated over the centuries that suggests this skill is transferable to many other things. Butler speaks the truth . Ill add to that point learn how to play devils advocate against yourself. The more you can reality-check your own processes and work, the better off youll be. The great computer scientistauthor Allen Holub made the connection between software development and the liberal arts specifically, the subject of history. Here was his point: what is history Reading and writing. What is software development Among other things, reading and writing . I used to give my students T-SQL essay questions as practice tests. One student joked that I acted more like a law professor. Well, just like Coach Donny Haskins said in the movie Glory Road, my way is hard. I firmly believe in a strong intellectual foundation for any profession. Just like applications can benefit from frameworks, individuals and their thought processes can benefit from human frameworks as well. Thats the fundamental basis of scholarship. There is a story that back in the 1970s, IBM expanded their recruiting efforts in the major universities by focusing on the best and brightest of liberal arts graduates. Even then they recognized that the best readers and writers might someday become strong programmersystems analysts. (Feel free to use that story to any HR-type who insists that a candidate must have a computer science degree) And speaking of history: if for no other reason, its important to remember the history of product releases if Im doing work at a client site thats still using SQL Server 2008 or even (gasp) SQL Server 2005, I have to remember what features were implemented in the versions over time. Ever have a favorite doctor whom you liked because heshe explained things in plain English, gave you the straight truth, and earned your trust to operate on you Those are mad skills . and are the result of experience and HARD WORK that take years and even decades to cultivate. There are no guarantees of job success focus on the facts, take a few calculated risks when youre sure you can see your way to the finish line, let the chips fall where they may, and never lose sight of being just like that doctor who earned your trust. Even though some days I fall short, I try to treat my client and their data as a doctor would treat patients. Even though a doctor makes more money There are many clichs I detest but heres one I dont hate: There is no such thing as a bad question. As a former instructor, one thing that drew my ire was hearing someone criticize another person for asking a supposedly, stupid question. A question indicates a person acknowledges they have some gap in knowledge theyre looking to fill. Yes, some questions are better worded than others, and some questions require additional framing before they can be answered. But the journey from forming a question to an answer is likely to generate an active mental process in others. There are all GOOD things. Many good and fruitful discussions originate with a stupid question. I work across the board in SSIS, SSAS, SSRS, MDX, PPS, SharePoint, Power BI, DAX all the tools in the Microsoft BI stack. I still write some. NET code from time to time. But guess what I still spend so much time doing writing T-SQL code to profile data as part of the discovery process. All application developers should have good T-SQL chops. Ted Neward writes (correctly) about the need to adapt to technology changes. Ill add to that the need to adapt to clientemployer changes. Companies change business rules. Companies acquire other companies (or become the target of an acquisition). Companies make mistakes in communicating business requirements and specifications. Yes, we can sometimes play a role in helping to manage those changes and sometimes were the fly, not the windshield. These sometimes cause great pain for everyone, especially the I. T. people. This is why the term fact of life exists we have to deal with it. Just like no developer writes bug-free code every time, no I. T. person deals well with change every single time. One of the biggest struggles Ive had in my 28 years in this industry is showing patience and restraint when changes are flying from many different directions. Here is where my prior suggestion about searching for the rarified air can help. If you can manage to assimilate changes into your thought process, and without feeling overwhelmed, odds are youll be a significant asset. In the last 15 months Ive had to deal with a huge amount of professional change. Its been very difficult at times, but Ive resolved that change will be the norm and Ive tried to tweak my own habits as best I can to cope with frequent (and uncertain) change. Its hard, very hard. But as coach Jimmy Duggan said in the movie A League of Their Own: Of course its hard. If it wasnt hard, everyone would do it. The hard, is what makes it great . A powerful message. Theres been talk in the industry over the last few years about conduct at professional conferences (and conduct in the industry as a whole). Many respected writers have written very good editorials on the topic. Heres my input, for what its worth. Its a message to those individuals who have chosen to behave badly: Dude, it shouldnt be that hard to behave like an adult. A few years ago, CoDe Magazine Chief Editor Rod Paddock made some great points in an editorial about Codes of Conduct at conferences. Its definitely unfortunate to have to remind people of what they should expect out of themselves. But the problems go deeper. A few years ago I sat on a five-person panel (3 women, 2 men) at a community event on Women in Technology. The other male stated that men succeed in this industry because the Y chromosome gives men an advantage in areas of performance. The individual who made these remarks is a highly respected technology expert, and not some bozo making dongle remarks at a conference or sponsoring a programming contest where first prize is a date with a bikini model. Our world is becoming increasingly polarized (just watch the news for five minutes), sadly with emotion often winning over reason. Even in our industry, recently I heard someone in a position of responsibility bash software tool XYZ based on a ridiculous premise and then give false praise to a competing tool. So many opinions, so many arguments, but heres the key: before taking a stand, do your homework and get the facts . Sometimes both sides are partly rightor wrong. Theres only one way to determine: get the facts. As Robert Heinlein wrote, Facts are your single clue get the facts Of course, once you get the facts, the next step is to express them in a meaningful and even compelling way. Theres nothing wrong with using some emotion in an intellectual debate but it IS wrong to replace an intellectual debate with emotion and false agenda. A while back I faced resistance to SQL Server Analysis Services from someone who claimed the tool couldnt do feature XYZ. The specifics of XYZ dont matter here. I spent about two hours that evening working up a demo to cogently demonstrate the original claim was false. In that example, it worked. I cant swear it will always work, but to me thats the only way. Im old enough to remember life at a teen in the 1970s. Back then, when a person lost hisher job, (often) it was because the person just wasnt cutting the mustard. Fast-forward to today: a sad fact of life is that even talented people are now losing their jobs because of the changing economic conditions. Theres never a full-proof method for immunity, but now more than ever its critical to provide a high level of what I call the Three Vs (value, versatility, and velocity) for your employerclients. I might not always like working weekends or very late at night to do the proverbial work of two people but then I remember there are folks out there who would give anything to be working at 1 AM at night to feed their families and pay their bills. Always be yourselfyour BEST self. Some people need inspiration from time to time. Heres mine: the great sports movie, Glory Road. If youve never watched it, and even if youre not a sports fan I can almost guarantee youll be moved like never before. And Ill close with this. If you need some major motivation, Ill refer to a story from 2006. Jason McElwain, a high school student with autism, came off the bench to score twenty points in a high school basketball game in Rochester New York. Heres a great YouTube video. His mother said it all . This is the first moment Jason has ever succeeded and is proud of himself. I look at autism as the Berlin Wall. He cracked it. To anyone who wanted to attend my session at todays SQL Saturday event in DC I apologize that the session had to be cancelled. I hate to make excuses, but a combination of getting back late from Detroit (client trip), a car thats dead (blown head gasket), and some sudden health issues with my wife have made it impossible for me to attend. Back in August, I did the same session (ColumnStore Index) for PASS as a webinar. You can go to this link to access the video (itll be streamed, as all PASS videos are streamed) The link does require that you fill out your name and email address, but thats it. And then you can watch the video. Feel free to contact me if you have questions, at kgoffkevinsgoff. net November 15, 2013 Getting started with Windows Azure and creating SQL Databases in the cloud can be a bit daunting, especially if youve never tried out any of Microsofts cloud offerings. Fortunately, Ive created a webcast to help people get started. This is an absolute beginners guide to creating SQL Databases under Windows Azure. It assumes zero prior knowledge of Azure. You can go to the BDBI Webcasts of this website and check out my webcast (dated 11102013). Or you can just download the webcast videos right here: here is part 1 and here is part 2. You can also download the slide deck here. November 03, 2013 Topic this week: SQL Server Snapshot Isolation Levels, added in SQL Server 2005. To this day, there are still many SQL developers, many good SQL developers who either arent aware of this feature, or havent had time to look at it. Hopefully this information will help. Companion webcast will be uploaded in the next day look for it in the BDBI Webcasts section of this blog. October 26, 2013 Im going to start a weekly post of T-SQL tips, covering many different versions of SQL Server over the years Heres a challenge many developers face. Ill whittle it down to a very simple example, but one where the pattern applies to many situations. Suppose you have a stored procedure that receives a single vendor ID and updates the freight for all orders with that vendor id. create procedure dbo. UpdateVendorOrders update Purchasing. PurchaseOrderHeader set Freight Freight 1 where VendorID VendorID Now, suppose we need to run this for a set of vendor IDs. Today we might run it for three vendors, tomorrow for five vendors, the next day for 100 vendors. We want to pass in the vendor IDs. If youve worked with SQL Server, you can probably guess where Im going with this. The big question is how do we pass a variable number of Vendor IDs Or, stated more generally, how do we pass an array, or a table of keys, to a procedure Something along the lines of exec dbo. UpdateVendorOrders SomeListOfVendors Over the years, developers have come up with different methods: Going all the way back to SQL Server 2000, developers might create a comma-separated list of vendor keys, and pass the CSV list as a varchar to the procedure. The procedure would shred the CSV varchar variable into a table variable and then join the PurchaseOrderHeader table to that table variable (to update the Freight for just those vendors in the table). I wrote about this in CoDe Magazine back in early 2005 (code-magazinearticleprint. aspxquickid0503071ampprintmodetrue. Tip 3) In SQL Server 2005, you could actually create an XML string of the vendor IDs, pass the XML string to the procedure, and then use XQUERY to shred the XML as a table variable. I also wrote about this in CoDe Magazine back in 2007 (code-magazinearticleprint. aspxquickid0703041ampprintmodetrue. Tip 12)Also, some developers will populate a temp table ahead of time, and then reference the temp table inside the procedure. All of these certainly work, and developers have had to use these techniques before because for years there was NO WAY to directly pass a table to a SQL Server stored procedure. Until SQL Server 2008 when Microsoft implemented the table type. This FINALLY allowed developers to pass an actual table of rows to a stored procedure. Now, it does require a few steps. We cant just pass any old table to a procedure. It has to be a pre-defined type (a template). So lets suppose we always want to pass a set of integer keys to different procedures. One day it might be a list of vendor keys. Next day it might be a list of customer keys. So we can create a generic table type of keys, one that can be instantiated for customer keys, vendor keys, etc. CREATE TYPE IntKeysTT AS TABLE ( IntKey int NOT NULL ) So Ive created a Table Typecalled IntKeysTT . Its defined to have one column an IntKey. Nowsuppose I want to load it with Vendors who have a Credit Rating of 1..and then take that list of Vendor keys and pass it to a procedure: DECLARE VendorList IntKeysTT INSERT INTO VendorList SELECT BusinessEntityID from Purchasing. Vendor WHERE CreditRating 1 So, I now have a table type variable not just any table variable, but a table type variable (that I populated the same way I would populate a normal table variable). Its in server memory (unless it needs to spill to tempDB) and is therefore private to the connectionprocess. OK, can I pass it to the stored procedure now Well, not yet we need to modify the procedure to receive a table type. Heres the code: create procedure dbo. UpdateVendorOrdersFromTT IntKeysTT IntKeysTT READONLY update Purchasing. PurchaseOrderHeader set Freight Freight 1 FROM Purchasing. PurchaseOrderHeader JOIN IntKeysTT TempVendorList ON PurchaseOrderHeader. VendorID Te mpVendorList. IntKey Notice how the procedure receives the IntKeysTT table type as a Table Type (again, not just a regular table, but a table type). It also receives it as a READONLY parameter. You CANNOT modify the contents of this table type inside the procedure. Usually you wont want to you simply want to read from it. Well, now you can reference the table type as a parameter and then utilize it in the JOIN statement, as you would any other table variable. So there you have it. A bit of work to set up the table type, but in my view, definitely worth it. Additionally, if you pass values from. NET, youre in luck. You can pass an ADO. NET data table (with the same tablename property as the name of the Table Type) to the procedure. For. NET developers who have had to pass CSV lists, XML strings, etc. to a procedure in the past, this is a huge benefit. Finally I want to talk about another approach people have used over the years. SQL Server Cursors. At the risk of sounding dogmatic, I strongly advise against Cursors, unless there is just no other way. Cursors are expensive operations in the server, For instance, someone might use a cursor approach and implement the solution this way: DECLARE VendorID int DECLARE dbcursor CURSOR FASTFORWARD FOR SELECT BusinessEntityID from Purchasing. Vendor where CreditRating 1 FETCH NEXT FROM dbcursor INTO VendorID WHILE FETCHSTATUS 0 EXEC dbo. UpdateVendorOrders VendorID FETCH NEXT FROM dbcursor INTO VendorID The best thing Ill say about this is that it works. And yes, getting something to work is a milestone. But getting something to work and getting something to work acceptably are two different things. Even if this process only takes 5-10 seconds to run, in those 5-10 seconds the cursor utilizes SQL Server resources quite heavily. Thats not a good idea in a large production environment. Additionally, the more the of rows in the cursor to fetch and the more the number of executions of the procedure, the slower it will be. When I ran both processes (the cursor approach and then the table type approach) against a small sampling of vendors (5 vendors), the processing times where 260 ms and 60 ms, respectively. So the table type approach was roughly 4 times faster. But then when I ran the 2 scenarios against a much larger of vendors (84 vendors), the different was staggering 6701 ms versus 207 ms, respectively. So the table type approach was roughly 32 times faster. Again, the CURSOR approach is definitely the least attractive approach. Even in SQL Server 2005, it would have been better to create a CSV list or an XML string (providing the number of keys could be stored in a scalar variable). But now that there is a Table Type feature in SQL Server 2008, you can achieve the objective with a feature thats more closely modeled to the way developers are thinking specifically, how do we pass a table to a procedure Now we have an answer Hope you find this feature help. Feel free to post a comment.
No comments:
Post a Comment