2010-08-19 3 views
0

Une application de la mienne essaie d'exécuter une requête count (*) qui revient après environ 30 minutes. Ce qui est étrange, c'est que la requête est très simple et les tables impliquées sont grandes, mais pas gigantesques (10 000 et 50 000 enregistrements).Requête SQL Oracle exécutée pour (presque) à jamais

La requête qui prend 30 minutes est la suivante:

select count(*) 
from RECORD r inner join GROUP g 
    on g.GROUP_ID = r.GROUP_ID 
where g.BATCH_ID = 1 and g.ENABLED = 'Y' 

Le schéma de base de données est essentiellement:

create table BATCH (
    BATCH_ID int not null, 
    [other columns]..., 
    CONSTRAINT PK_BATCH PRIMARY KEY (BATCH_ID) 
); 

create table GROUP (
    GROUP_ID int not null, 
    BATCH_ID int, 
    ENABLED char(1) not null, 
    [other columns]..., 
    CONSTRAINT PK_GROUP PRIMARY KEY (GROUP_ID), 
    CONSTRAINT FK_GROUP_BATCH_ID FOREIGN KEY (BATCH_ID) 
     REFERENCES BATCH (BATCH_ID), 
    CONSTRAINT CHK_GROUP_ENABLED CHECK(ENABLED in ('Y', 'N')) 
); 

create table RECORD (
    GROUP_ID int not null, 
    RECORD_NUMBER int not null, 
    [other columns]..., 
    CONSTRAINT PK_RECORD PRIMARY KEY (GROUP_ID, RECORD_NUMBER), 
    CONSTRAINT FK_RECORD_GROUP_ID FOREIGN KEY (GROUP_ID) 
     REFERENCES GROUP (GROUP_ID) 
); 

create index IDX_GROUP_BATCH_ID on GROUP(BATCH_ID); 

Je vérifie s'il y a des blocs dans la base de données et il n'y en a pas. J'ai aussi couru les morceaux de la requête et tous, sauf les deux derniers instantanément retourné suivants:

select count(*) from RECORD -- 55,501 

select count(*) from GROUP -- 11,693 

select count(*) 
from RECORD r inner join GROUP g 
    on g.GROUP_ID = r.GROUP_ID 
-- 55,501 

select count(*) 
from GROUP g 
where g.BATCH_ID = 1 and g.ENABLED = 'Y' 
-- 3,112 

select count(*) 
from RECORD r inner join GROUP g 
    on g.GROUP_ID = r.GROUP_ID 
where g.BATCH_ID = 1 
-- 27,742 - took around 5 minutes to run 

select count(*) 
from RECORD r inner join GROUP g 
    on g.GROUP_ID = r.GROUP_ID 
where g.ENABLED = 'Y' 
-- 51,749 - took around 5 minutes to run 

Quelqu'un peut-il expliquer ce qui se passe? Comment puis-je améliorer les performances de la requête? Merci.

Répondre

1

Un collègue a trouvé le problème. C'est parce que les statistiques du tableau n'étaient pas mises à jour et la dernière fois que la table a été analysée, c'était il y a quelques mois (quand la table était vide). J'ai couru analyser les statistiques de calcul RECORD de la table et maintenant la requête revient en moins d'une seconde.

Je dois parler à l'administrateur de base de données de la raison pour laquelle les statistiques de la table n'ont pas été mises à jour.

+0

Maintenant, je suis fou, je n'ai pas pensé à ça, ça m'est arrivé à plusieurs reprises dans un environnement de travail lors de la mise en ligne. *secoue la tête*. Je suis content que vous l'ayez compris. – XstreamINsanity

+0

Je vous suggère de prendre un grand cluebat avec vous. –

0
SELECT COUNT(*) 
FROM RECORD R 
LEFT OUTER JOIN GROUP G ON G.GROUP_ID = R.GROUP_ID 
     AND G.BATCH_ID = 1 
     AND G.ENABLED = 'Y' 

Essayez-le et faites-moi savoir comment cela se passe. Ne pas dire c'est la réponse, mais comme je n'ai pas accès à une base de données en ce moment, je ne peux pas la tester. J'espère que ça marche pour toi.

+0

Cela prend plus de 5 minutes. – jthg

+0

Essayez au lieu de COUNT (*) un COUNT (columnName) et voyez si cela fait quelque chose. Doutez, mais ça vaut le coup. – XstreamINsanity

0

Un plan d'explication serait un bon point de départ.

Voir ici:

Strange speed changes with sql query

pour savoir comment utiliser le Si cela ne montre pas la syntaxe plan expliquer (. Et requête pour voir le résultat)

quelque chose de suspect, vous aurez probablement vouloir regarder une trace.

Questions connexes