2010-02-08 3 views
0

Je travaille sur une application web pilotée par les données qui utilise une base de données SQL 2005 (édition standard).La table massive dans la base de données SQL 2005 a besoin de meilleures performances!

Une des tables est plutôt grande (8 millions + lignes larges avec environ 30 colonnes). La taille de la table affecte évidemment les performances du site Web qui sélectionne les éléments de la table via les procs stockés. La table est indexée mais les performances restent faibles en raison de la quantité de lignes dans la table - cela fait partie du problème - la table est aussi lue que mise à jour, donc nous ne pouvons pas ajouter/supprimer des index sans faire un les opérations pire.

Le but que j'ai ici est d'augmenter les performances lors de la sélection des éléments de la table. La table contient des données 'courantes' et des données anciennes/à peine touchées. La solution la plus efficace que nous pouvons envisager à ce stade est de séparer la table en 2, soit un pour les anciens (avant une certaine date, disons 1 janvier 2005) et un pour les nouveaux items (égal ou supérieur au 1er janvier 2005) . Nous connaissons des choses comme les vues partitionnées distribuées - mais toutes ces fonctionnalités nécessitent l'édition Enterprise, que le client n'achètera pas (et non, le lancement de matériel ne se produira pas non plus).

Répondre

3

Vous pouvez toujours lancer votre propre "partitionnement DPV pauvre", même si elle ne sent pas la bonne façon de le faire. Ceci est juste une approche conceptuelle large:

  1. Créer une nouvelle table pour les données de l'année en cours - même structure, mêmes index. Ajustez la procédure stockée qui écrit dans la grande table principale pour écrire dans les deux tables (temporairement). Je recommande de faire la logique dans la procédure stockée dites SI CURRENT_TIMESTAMP> = '[une date entière sans temps]' - cela facilitera le remplissage des données dans cette table qui est antérieure à la modification de la procédure qui commence à s'y connecter.

  2. Créez une nouvelle table pour chaque année de votre historique en utilisant SELECT INTO dans la table principale. Vous pouvez le faire dans une base de données différente sur la même instance pour éviter le surcoût dans la base de données en cours. Les données historiques ne vont pas changer je suppose, donc dans cette autre base de données, vous pourriez même le faire lire seulement quand c'est fait (ce qui améliorera considérablement les performances de lecture). Une fois que vous avez une copie de la table entière, vous pouvez créer des vues qui référencent uniquement l'année en cours, une autre vue qui référence 2005 à l'année en cours (en utilisant UNION ALL entre la table actuelle et celles de l'autre base de données qui sont> = 2005), et un autre qui fait référence aux trois ensembles de tables (ceux qui sont mentionnés et ceux qui datent d'avant 2005). Bien sûr, vous pouvez casser encore plus, mais je voulais juste garder le concept minimal. Modifiez vos procédures stockées qui lisent les données pour qu'elles soient «plus intelligentes». Si la plage de dates demandée tombe dans l'année civile en cours, utilisez la plus petite vue locale uniquement. si la plage de dates est> = 2005, utilisez la deuxième vue, sinon utilisez la troisième vue. Vous pouvez suivre une logique similaire avec des procédures stockées qui écrivent, si vous faites plus que simplement insérer de nouvelles données qui ne concernent que l'année en cours. À ce stade, vous devriez être en mesure d'arrêter d'insérer dans la table massive et, une fois que tout fonctionne, laissez tomber et récupérer de l'espace disque (et je veux dire libérer de l'espace dans le fichier de données (s) pour la réutilisation, ne pas effectuer un rétrécissement db - puisque vous utiliserez cet espace à nouveau).

Je n'ai pas tous les détails de votre situation, mais veuillez faire un suivi si vous avez des questions ou des préoccupations.J'ai utilisé cette approche dans plusieurs projets de migration, dont un qui se déroule actuellement.

+0

Merci pour la réponse, nous étions initialement sous l'impression que les données historiques étaient encore modifiables, mais ont récemment découvert que nous pouvons le rendre en lecture seule. Donc, votre réponse semble être une bonne option, applaudit :) – Scozzard

1

Reconstruisez tous vos index. Cela augmentera les performances des requêtes. Comment faire est this et plus sur l'effet sur la reconstruction de l'index cluster et non-cluster here

Deuxièmement effectuer de fragmentation sur votre disque sur lequel la base de données est stockée.

+0

Pour les tâches de maintenance d'index comme rebuild/reorganize, vous devez utiliser l'un de ces utilitaires pour vous aider à déterminer les index à reconstruire et à réorganiser. Le script de Michelle Ufford est ici (regardez son blog pour une nouvelle version à venir): http://sqlfool.com/2009/06/index-defrag-script-v30/ et le script d'Ola Hallengren est ici: http: // ola. hallengren.com/ –

+0

Nous réorganisons fréquemment et reconstruisons les index de manière appropriée dans le cadre de la maintenance de routine. Les index sont aussi optimisés qu'ils peuvent l'être. Le disque a été aussi défragmenté qu'il le sera - le système est un système de 24 heures sans équilibrage de charge, donc nous ne pouvons pas mettre le système hors ligne assez longtemps pour faire une défragmentation complète du disque. Je sais que ce n'est pas idéal, mais ce sont les ruptures dans un monde qui n'est pas idéal. – Scozzard

+0

Quels sont les paramètres de croissance automatique du (des) fichier (s)? La fragmentation du système de fichiers ne devrait pas vraiment être un problème de performances, à moins que votre paramètre de croissance automatique ne soit vraiment petit ou que la disposition du disque soit mal planifiée. –

1

performance est médiocre en raison de l'énorme quantité de lignes dans la table

8 millions de lignes ne sonnent pas tout ce que fou. Avez-vous vérifié vos plans de requête?

la table est tout aussi lu que mis à jour

Vous mettez à jour en fait une colonne indexée ou est-il également lu et inséré à?

(et non, jeter le matériel à elle ne va pas se passer non plus)

C'est dommage parce que la RAM est la saleté pas cher.

+0

Votre droite, 8 millions de lignes n'est pas fou. Cependant, la table est la plus couramment utilisée dans le système, fréquemment utilisée pour les lectures et les écritures. Les plans de requête pour les lectures et les écritures sont misérables en essayant d'optimiser l'autre - en d'autres termes, nous sommes dans une impasse. – Scozzard

+0

Re: Lire/Mis à jour Oui, mon mauvais, je voulais dire écrire (inséré) - nos opérations d'écriture dans cette table sont responsables de 30% de nos délais d'attente SQL dans le système. Malheureusement, comme il s'agit d'une application web synchrone, nous n'avons pas le luxe d'allonger le délai d'attente car la performance est déjà une plainte courante et cela ne ferait qu'empirer les choses. Nous nous rendons compte que la structure actuelle ne va pas continuer à fonctionner et que nous recherchons la meilleure structure alternative qui n'impliquera pas la reconstruction de l'application à partir de zéro (ce qui bien qu'idéal, ne se produira pas). – Scozzard

+0

Re: RAM - oui vous avez raison. Malheureusement, dans le monde de la sous-traitance, nous pouvons vous conseiller autant que nous le souhaiterions, mais en fin de compte la décision revient aux clients. Ils viennent juste d'acheter du nouveau matériel et une nouvelle actualisation (ou même une mise à niveau) est prévue dans 3 ans. À un moment donné également, la structure de la base de données doit être corrigée en fonction de la quantité de données anciennes et actuelles qui est redondante - nous aimerions essayer un correctif plutôt qu'un correctif. – Scozzard

Questions connexes