2010-10-21 5 views
2

Nous avons une base de données Oracle 9i avec 7 tables, chacune avec plus de 15 millions d'enregistrements. Il n'y a pas de relation entre la table, c'est-à-dire aucune clé étrangère.Comment optimiser la base de données Oracle?

Voici un exemple de l'une des tables

CREATE TABLE GSS.SHOWPD 
(
    INSERVID   VARCHAR2(7 CHAR)   NOT NULL, 
    CAGEPOS   VARCHAR2(8 CHAR)   DEFAULT NULL, 
    DETAILEDSTATE  VARCHAR2(100 CHAR)   DEFAULT NULL, 
    FAILEDMB   NUMBER      DEFAULT NULL, 
    FREECHUNK   NUMBER      DEFAULT NULL, 
    FREEMB   NUMBER      DEFAULT NULL, 
    FWREV    VARCHAR2(100 CHAR)   DEFAULT NULL, 
    FWSTATUS   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    AID    NUMBER      DEFAULT NULL, 
    LDA    VARCHAR2(100 CHAR)   DEFAULT NULL, 
    MANUF    VARCHAR2(100 CHAR)   DEFAULT NULL, 
    AMODEL   VARCHAR2(4000 CHAR)   DEFAULT NULL, 
    NODEWWN   VARCHAR2(64 CHAR)   DEFAULT NULL, 
    NRMUNUSEDFAIL  VARCHAR2(100 CHAR)   DEFAULT NULL, 
    NRMUNUSEDFREE  VARCHAR2(100 CHAR)   DEFAULT NULL, 
    NRMUNUSEDUNAVAIL VARCHAR2(100 CHAR)   DEFAULT NULL, 
    NRMUSEDFAIL  VARCHAR2(100 CHAR)   DEFAULT NULL, 
    NRMUSEDOK   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    AORDER   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    PATHA0   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    PATHA1   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    PATHB0   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    PATHB1   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    PORTA0   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    PORTA1   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    PORTB0   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    PORTB1   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    RDCERR   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    REUERR   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    SERIAL   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    SIZEMB   NUMBER      DEFAULT NULL, 
    SPARECHUNK  VARCHAR2(100 CHAR)   DEFAULT NULL, 
    SPAREMB   NUMBER      DEFAULT NULL, 
    SPEEDKRPM   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    SPRUNUSEDFAIL  VARCHAR2(100 CHAR)   DEFAULT NULL, 
    SPRUNUSEDFREE  VARCHAR2(100 CHAR)   DEFAULT NULL, 
    SPRUNUSEDUNINIT VARCHAR2(100 CHAR)   DEFAULT NULL, 
    SPRUSEDFAIL  VARCHAR2(100 CHAR)   DEFAULT NULL, 
    SPRUNUSEDOK  VARCHAR2(100 CHAR)   DEFAULT NULL, 
    STATE    VARCHAR2(100 CHAR)   DEFAULT NULL, 
    TEMPDEGC   NUMBER      DEFAULT NULL, 
    TOTALCHUNK  VARCHAR2(100 CHAR)   DEFAULT NULL, 
    ATYPE    VARCHAR2(100 CHAR)   DEFAULT NULL, 
    UNAVAILABLEMB  NUMBER      DEFAULT NULL, 
    VOLUMEMB   NUMBER      DEFAULT NULL, 
    WRCERR   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    WRUERR   VARCHAR2(100 CHAR)   DEFAULT NULL, 
    COMMANDTIMESTAMP TIMESTAMP(6)    DEFAULT NULL NOT NULL, 
    FETCHTIMESTAMP TIMESTAMP(6)    DEFAULT NULL NOT NULL 
) 

Notez que INSERVID peut être l'un des 1400 types. Il est donc possible d'avoir 1400 tables chacune dédiées à un serveur. Serait-ce une chose folle à faire? Je me demande.

Nous parcourons le numéro d'inservs et exécutons toutes nos requêtes à leur encontre. À l'heure actuelle, nous purifions les données, de sorte que nous ne prévoyons pas dépasser 15 millions d'enregistrements.

1) Nous avons des requêtes distinctes, ce qui nécessite un scan complet de la table. Le plan d'exécution d'Oracle montre que nous effectuons un scan complet de la table.

select distinct(inservid),commandtimestamp from statpd order by commandtimestamp desc; 

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------- 
| Id | Operation   | Name  | Rows | Bytes | Cost | 
-------------------------------------------------------------------- 
| 0 | SELECT STATEMENT  |    | 665 | 13300 | 79488 | 
| 1 | SORT UNIQUE   |    | 665 | 13300 | 69088 | 
| 2 | TABLE ACCESS FULL | STATPD  | 4128K| 78M| 19406 | 
-------------------------------------------------------------------- 
Note: cpu costing is off 
10 rows selected. 

2) Chaque table a un index sur inserv id. Cela a aidé à réduire le coût des requêtes, que pouvons-nous faire de plus? Des astuces/astuces pour rendre les choses plus vite?

3) Cela a-t-il un sens si nous faisons en sorte que nos requêtes sql s'exécutent sur chaque table en tant que scripts parallèles s'exécutant sur chaque table. Cela entraînerait-il un achèvement plus rapide?

4) Nous avons assez de RAM pour charger toute la DB en mémoire. Est-ce possible avec ORACLE?

Merci à l'avance

+1

Je ne pense pas distincte par elle-même entraînerait un balayage complet de la table. – BlackICE

+0

@David affichant la sortie du plan d'exécution pour une meilleure compréhension –

+0

@David s'il vous plaît jeter un oeil à la sortie du plan d'exécution pour en savoir plus –

Répondre

5

1-2) Avoir un index sur (inservid,commandtimestamp) remplacera FULL TABLE SCAN avec un (FAST) SCAN INDEX COMPLET depuis l'une des deux colonnes est NOT NULL (d'où le DB peut utiliser la index au lieu de la table). Cela devrait être plus rapide que l'analyse de table complète, mais toutes les entrées d'index de 15+ M lignes seront lues. Vous pouvez obtenir un temps de réponse plus rapide avec une table précalculée (par exemple, une vue matérialisée Fast Refresh), dans ce cas, vous obtiendrez probablement une performance sur les opérations DML sur la table (insérer/mettre à jour/supprimer sera plus lent).)

3) Le fait que les requêtes soient exécutées en parallèle vous donnera un avantage si vous avez encore de la bande passante E/S. En ce moment, votre analyse de table complète lira probablement beaucoup de lignes à partir des disques. À moins que vos tables résident sur des périphériques physiquement séparés, le gain en passant en parallèle sera minime. 4) Le chargement dans la mémoire RAM s'effectue principalement automatiquement dans Oracle: dans la plupart des cas, Oracle fait un bon travail en plaçant les données fréquemment utilisées en mémoire.

+0

Avoir un index sur (inservid, commandtimestamp) réellement fait augmenter le coût dans le plan d'exécution dans notre expérience –

+0

Merci pour les entrées supplémentaires ... besoin de les explorer :) merci –

+0

@Ankur Gupta: créez l'index, analysez la table et l'index et mesurez lequel est le plus rapide (exécutez la requête deux fois, une avec l'analyse complète, l'autre avec le chemin d'index, vous aurez probablement besoin de faire allusion à la requête forcez le db à utiliser un scan complet). Cette méthode sera plus fiable que la comparaison du coût de l'optimiseur. –

2

Partie 4, ce n'est généralement pas nécessaire. Dans 9i vous pouvez configurer un pool de tampons spécial "keep" pour essayer de garder vos index en mémoire. (mais puisqu'il n'y a pas de support disponible pour Oracle maintenant, ce n'est peut-être pas le bon moment pour expérimenter avec des fonctionnalités que vous n'avez pas encore utilisées)

Vos clients sont sur la machine locale, sinon le client peut bénéficier de la fonction 11g client (côté » cache de résultats, afin de minimiser le serveur de base de données allers-retours.

Excerpt from Oracle® Database Performance Tuning Guide 11g Release 2 (11.2) Part Number E16638-03

7.6.2.1 Comment fonctionne le cache résultat client les magasins de cache de résultats client les résultats de la requête la plus externe, quelles sont les colonnes définies par l'application OCI.Les sous-requêtes et les blocs de requête ne sont pas mis en cache.

La figure 7-4 illustre un processus client avec une session de connexion à la base de données. Ce processus client a un cache de résultat client partagé entre plusieurs sessions d'applications exécutées dans le processus client. Si la première session d'application exécute une requête, elle extrait les lignes de la base de données et les met en cache dans le cache des résultats du client. Si d'autres sessions d'application exécutent la même requête, elles récupèrent également les lignes du cache des résultats du client.

alt text

+0

Nous utilisons 9i et il n'y a aucun moyen que nous pouvons mettre à niveau vers 10/11 ... doivent rester avec cela. –

+0

Oracle 9i Release 2 (9.2.0) Support étendu Fin: 30-Jul-2010 ... (ou ont-ils prolongé cela?) – oluies

+0

point est que nous ne pouvons pas acheter 10/11 donc nous restons mis avec cela. –

1

par 1), 4) i d'accord avec Vincent. 2) vous avez de longues rangées - donc il peut être bon d'avoir un plus grand db_block_size - 16Kb ou 32Kb et il peut être utile d'essayer de compresser sur votre table. Vérifiez également votre fichier db_file_multiblock_read_count. peut être partiton - distribuez-le sur autant de lecteurs que vous avez. 3) vous pouvez jouer avec un indice parallèle pour voir comment cela se passe.

+0

Merci pour 2) va investir du temps à comprendre comment je peux le faire et voir comment cela améliore ma vitesse d'exécution ... Merci ... –

0

Votre modèle de données est rompu. Pouvez-vous fournir plus de détails sur les requêtes que vous exécutez? L'ajout d'index ne vous aidera que jusqu'à un certain point.

Questions connexes