Consumo de cpu estourando com pesquisa SQL

Firebird

04/02/2005

Tem algumas pesquisas sql que estamos fazendo aqui e o consumo de cpu e muito grande tornando os outros computadores lentos demais, alguem tem algura sugestão de como podemos fazer para não acontecer isso mesmo que a consulta tenha que demorar mais ???

Valeu galera


Sremulador

Sremulador

Curtidas 0

Respostas

Afarias

Afarias

04/02/2005

Bom, teoricamente esse problema foi minimizado nas versões mais recentes do IB e do FB. Qual versão vc está executando?


T+


GOSTEI 0
Sremulador

Sremulador

04/02/2005

bem estou utilizando o fb 1.5.2.4721

eu já tentei de tudo mas quando tenho que fazer certas pesquisas principalmente quando tem group´s ...


GOSTEI 0
Afarias

Afarias

04/02/2005

é broca :) ... vc não pode otimizar as consultas? já viu o plano de consulta utilizado pelo FB? já pensou em usar um SP para consultas assim?


T+


GOSTEI 0
Sremulador

Sremulador

04/02/2005

bem estou utilizando uma view mas ja tinha começado a contruir um sp pra ver se consigo dar um geito nisso.


GOSTEI 0
Afarias

Afarias

04/02/2005

E quanto ao plano, verificou se é o ´melhor´?


T+


GOSTEI 0
Sremulador

Sremulador

04/02/2005

bem quando eu faço sem os groups até que e rapida a pesuisa porem quando coloco fica triste, o plano e automatico mas coloquei em gráfico e ele esta utilizando todos os indices possiveis...


GOSTEI 0
Afarias

Afarias

04/02/2005

Quanto mais campos em um grupo, realmente mais lenta é a pesquisa. Use apenas no grupo os campos realmente necessários.

T+


GOSTEI 0
Sremulador

Sremulador

04/02/2005

Bem afarias eu estou fazendo na verdade 2 groups um para uma coluna e outro para outra ex

select .... campo1col from tabela
where...
group...
union all
select campo1col .... from tabela
where...
group...

pois o resultado que quero tem que ser em coluna, você teria uma boa solução para este caso ???


GOSTEI 0
Afarias

Afarias

04/02/2005

não sem conhecer o WHERE, o GROUP, vc quase não postou nada.


T+


GOSTEI 0
Sremulador

Sremulador

04/02/2005

certo mestre ai vai o cod

SELECT F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB, SUM(CEVL * CEQT) as CEVL, SUM(CEVH * CEQT) AS CEVH, CAST (NULL AS DECIMAL (16,4)) AS CE, SUM (CEQT) AS CEQT, SUM ((CEFM + CEVH + CEVL) * (CEQT)) AS TOTAL FROM CONTA_AMB_PROCED
INNER JOIN CONTA_AMB_PROCED_MESTRE CAM ON(CPCD=CECP)
INNER JOIN ESPECIFICA_PROCEDCONV_DETALHE on (EPPC=CEPC)
INNER JOIN PROCEDIMENTO ON (PCCD=CEPC)
INNER JOIN PRESTADOR ON (PRCD=CPPR)
INNER JOIN FATURA_DETALHE_AMB ON (F2AM=CPAM)
INNER JOIN FATURA_MESTRE_AMB ON (F1CD=F2F1)
INNER JOIN AMBULATORIO ON (AMCD=CPAM)
WHERE CEAM=CAM.CPAM AND AMTH = ´C´ AND EPPV=CETB AND CETA IN(10,12)
GROUP BY F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB
UNION ALL
SELECT F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB, SUM(CEVL * CEQT) as CEVL, CAST (NULL AS DECIMAL (16,4)) AS CE, SUM(CEVH * CEQT) AS CEVH, SUM (CEQT) AS CEQT, SUM ((CEFM + CEVH + CEVL) * (CEQT)) AS TOTAL FROM CONTA_AMB_PROCED
INNER JOIN CONTA_AMB_PROCED_MESTRE CAM ON(CPCD=CECP)
INNER JOIN ESPECIFICA_PROCEDCONV_DETALHE on (EPPC=CEPC)
INNER JOIN PROCEDIMENTO ON (PCCD=CEPC)
INNER JOIN PRESTADOR ON (PRCD=CPPR)
INNER JOIN FATURA_DETALHE_AMB ON (F2AM=CPAM)
INNER JOIN FATURA_MESTRE_AMB ON (F1CD=F2F1)
INNER JOIN AMBULATORIO ON (AMCD=CPAM)
WHERE CEAM=CAM.CPAM AND AMTH = ´E´ AND EPPV=CETB AND CETA IN(10,12)
GROUP BY F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB

da pra entender, na union o cod e o mesmo apenas a restrição muda para que o valor que desejo saia na outra coluna, você acha que tem como fazer isso


GOSTEI 0
Afarias

Afarias

04/02/2005

pelo q posso entender, a única coisa q muda entre os 2 selects é:

no primeiro: AMTH = ´C´ e no outro AMTH = ´E´ -- vc poderia evitar o union usando AMHT IN (´C´, ´E´)

sua query realmente está bem pessada, tem *muitos* grupos e ainda corre 2 vezes por causa do UNION

além dos muitos JOINS (todos eles estão usando os índeces né? se for, ok)

talvês o ´pior´ da história é q o WHERE não parece conter nada q possa efetivamente otimizar a query:

|WHERE CEAM=CAM.CPAM

me parece mais um join

|AND AMTH = ´C´

campo de baixa seletividade

|AND EPPV=CETB

??

|AND CETA IN(10,12)

novamente, baixa seletividade

por esse WHERE vc deve estar fazendo algo como alguma seleção NATURAL -- quanto maior for a quntidade de registros desta tabela onde a seleção é NATURAL, mas lento é a consulta toda...


T+


GOSTEI 0
Sremulador

Sremulador

04/02/2005

pelo q posso entender, a única coisa q muda entre os 2 selects é:


não exatamente no select do 1º union eu separo uma coluna
CAST (NULL AS DECIMAL (16,4)) AS CE

ja na mesma posição no 2º union eu ja coloco
SUM(CEVL * CEQT) as CEVL

no primeiro: AMTH = ´C´ e no outro AMTH = ´E´ -- vc poderia evitar o union usando AMHT IN (´C´, ´E´)


sim mas e que na primeira union eu quero que o valor de E aparareça em uma coluna e a de C em outra...


GOSTEI 0
Afarias

Afarias

04/02/2005

sim mas e que na primeira union eu quero que o valor de E aparareça em uma coluna e a de C em outra...


OK


T+


GOSTEI 0
Sremulador

Sremulador

04/02/2005

teria como eu fazer uma procedure tipo if CAMPO = E valor soma com a quant atual else ...


GOSTEI 0
Afarias

Afarias

04/02/2005

Sim. Um procedure pode ser uma solução -- já q ao q parece vc não pode ter um WHERE melhor e pelo q vc disse o plano já está otimizado.



T+


GOSTEI 0
Sremulador

Sremulador

04/02/2005

Bem mestre tentei fazer a procedure mas não estou conseguindo pode me dar uma mãozinha como posso fazer para se caso for = E o valor do select soma com a variavel e retorna ficou assim meu sql

CREATE PROCEDURE RELPABFAEP (
FAT INTEGER)
RETURNS (
F1CD INTEGER,
F1CV INTEGER,
F1FF DATE,
F1RC DATE,
F1RP DATE,
F1CT CHAR (5),
PRDS VARCHAR (70),
CPPR VARCHAR (70),
PCSB CHAR (1),
CEVL DECIMAL (18, 2),
VALE DECIMAL (18, 2),
VALC DECIMAL (18, 2),
CEVH DECIMAL (18, 2),
CEQT INTEGER,
TOTAL DECIMAL (18, 2))
AS
DECLARE VARIABLE VALORC DECIMAL(18,2);
DECLARE VARIABLE VALORE DECIMAL(18,2);
DECLARE VARIABLE VALORG DECIMAL(18,2);
declare variable AMTH CHAR(1);
BEGIN
FOR SELECT F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB, SUM(CEVL * CEQT) as CEVL, SUM(CEVH * CEQT) AS CEVH, CAST (NULL AS DECIMAL (16,4)) AS CE, SUM (CEQT) AS CEQT, SUM ((CEFM + CEVH + CEVL) * (CEQT)) AS TOTAL FROM CONTA_AMB_PROCED
INNER JOIN CONTA_AMB_PROCED_MESTRE CAM ON(CPCD=CECP)
INNER JOIN ESPECIFICA_PROCEDCONV_DETALHE on (EPPC=CEPC)
INNER JOIN PROCEDIMENTO ON (PCCD=CEPC)
INNER JOIN PRESTADOR ON (PRCD=CPPR)
INNER JOIN FATURA_DETALHE_AMB ON (F2AM=CPAM)
INNER JOIN FATURA_MESTRE_AMB ON (F1CD=F2F1)
INNER JOIN AMBULATORIO ON (AMCD=CPAM)
WHERE CEAM=CAM.CPAM AND EPPV=CETB AND CETA IN(10,12) AND F1CD=:FAT
GROUP BY F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB
INTO F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB, CEVL, CEVH, CEQT, VALORG, TOTAL DO
if (:AMTH = ´C´) then VALORC=VALORC + VALORG;
if (:AMTH = ´E´) then VALORE=VALORE + VALORG;
VALE = VALORE;
VALC = VALORC;
SUSPEND;


GOSTEI 0
Fsflorencio

Fsflorencio

04/02/2005

Acho que deve funcionar assim:

CREATE PROCEDURE RELPABFAEP (
FAT INTEGER)
RETURNS (
F1CD INTEGER,
F1CV INTEGER,
F1FF DATE,
F1RC DATE,
F1RP DATE,
F1CT CHAR (5),
PRDS VARCHAR (70),
CPPR VARCHAR (70),
PCSB CHAR (1),
CEVL DECIMAL (18, 2),
VALE DECIMAL (18, 2),
VALC DECIMAL (18, 2),
CEVH DECIMAL (18, 2),
CEQT INTEGER,
TOTAL DECIMAL (18, 2))
AS
DECLARE VARIABLE VALORC DECIMAL(18,2);
DECLARE VARIABLE VALORE DECIMAL(18,2);
DECLARE VARIABLE VALORG DECIMAL(18,2);
declare variable AMTH CHAR(1);
BEGIN
FOR SELECT F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB, SUM(CEVL * CEQT) as CEVL, SUM(CEVH * CEQT) AS CEVH, CAST (NULL AS DECIMAL (16,4)) AS CE, SUM (CEQT) AS CEQT, SUM ((CEFM + CEVH + CEVL) * (CEQT)) AS TOTAL FROM CONTA_AMB_PROCED
INNER JOIN CONTA_AMB_PROCED_MESTRE CAM ON(CPCD=CECP)
INNER JOIN ESPECIFICA_PROCEDCONV_DETALHE on (EPPC=CEPC)
INNER JOIN PROCEDIMENTO ON (PCCD=CEPC)
INNER JOIN PRESTADOR ON (PRCD=CPPR)
INNER JOIN FATURA_DETALHE_AMB ON (F2AM=CPAM)
INNER JOIN FATURA_MESTRE_AMB ON (F1CD=F2F1)
INNER JOIN AMBULATORIO ON (AMCD=CPAM)
WHERE CEAM=CAM.CPAM AND EPPV=CETB AND CETA IN(10,12) AND F1CD=:FAT
GROUP BY F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB
INTO F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB, CEVL, CEVH, CEQT, VALORG, TOTAL DO
[b:7ecc0ff83d]BEGIN

if (:AMTH = ´C´) then
BEGIN
VALORC=VALORC + VALORG;
END

if (:AMTH = ´E´) then
BEGIN
VALORE=VALORE + VALORG;
END

VALE = VALORE;
VALC = VALORC;

SUSPEND;
END

END[/b:7ecc0ff83d]


GOSTEI 0
Afarias

Afarias

04/02/2005

o problema em ambos os códigos é o dois-pontos :

o correto é:

if (AMTH = ´C´) then 
  VALORC=VALORC + VALORG;


ou

if (AMTH = ´C´) then 
BEGIN 
  VALORC=VALORC + VALORG; 
END


T+


GOSTEI 0
Sremulador

Sremulador

04/02/2005

eu já tinha feito desta maneira eu fiz assim tb
DECLARE VARIABLE VALORC DECIMAL(18,2);
DECLARE VARIABLE VALORE DECIMAL(18,2);
BEGIN
FOR SELECT F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB, SUM(CEVL * CEQT) as CEVL, SUM(CEVH * CEQT) AS CEVH,
CASE AMTH WHEN ´C´ THEN VALORC [b:288266e9a9]=[/b:288266e9a9] SUM(CEVH * CEQT) END
WHEN ´E´ THEN VALORE [b:288266e9a9]=[/b:288266e9a9] SUM(CEVH * CEQT)
END,
SUM (CEQT) AS CEQT, SUM ((CEFM + CEVH + CEVL) * (CEQT)) AS TOTAL FROM CONTA_AMB_PROCED
INNER JOIN CONTA_AMB_PROCED_MESTRE CAM ON(CPCD=CECP)
INNER JOIN ESPECIFICA_PROCEDCONV_DETALHE on (EPPC=CEPC)
INNER JOIN PROCEDIMENTO ON (PCCD=CEPC)
INNER JOIN PRESTADOR ON (PRCD=CPPR)
INNER JOIN FATURA_DETALHE_AMB ON (F2AM=CPAM)
INNER JOIN FATURA_MESTRE_AMB ON (F1CD=F2F1)
INNER JOIN AMBULATORIO ON (AMCD=CPAM)
WHERE CEAM=CAM.CPAM AND EPPV=CETB AND CETA IN(10,12) AND F1CD=:FAT
GROUP BY F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB, AMTH
INTO F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB, CEVL, VALORE, VALORC, CEQT, TOTAL DO
SUSPEND;

porem o complador diz que p sinal de = não deve ser ali mas como vou fazer para o VALORE E C receber a soma dos valores ???


GOSTEI 0
Sremulador

Sremulador

04/02/2005

if (AMTH = ´C´) then VALORC=VALORC + VALORG;


mestre desta maneira 1º só me retorna uma linha da 2º me retorna certo porem não esta somando os valores para me retornar na SP


GOSTEI 0
Afarias

Afarias

04/02/2005

no CASE vc apenas calcula o valor do ´campo virtual´ ::


CASE AMTH 
  WHEN ´C´ THEN SUM(CEVH * CEQT) END 
  WHEN ´E´ THEN SUM(CEVH * CEQT) END
END



... na parte do INTO na posição desse campo vc coloca a variável q vai recebê-lo ::

INTO ..., :TEMP, ... DO
BEGIN
  IF (sei-lá-o-q) THEN
    VALORC = TEMP;
  ELSE
    VALORE = TEMP;
  SUSPEND;
END



T+


GOSTEI 0
Sremulador

Sremulador

04/02/2005

mestre tentei de diversas maneira fiz assim mas me retornou todos os valores do valorc nulos e somente uma linha, o que pode ser ???, quando fiz com o case ... when ... valorc = ele diz que tem um erro no sinal de = o que pode ser ???

FOR SELECT F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB, SUM(CEVL * CEQT) as CEVL, SUM(CEVH * CEQT) AS CEVH, SUM (CEQT) AS CEQT, SUM ((CEFM + CEVH + CEVL) * (CEQT)) AS TOTAL FROM CONTA_AMB_PROCED
INNER JOIN CONTA_AMB_PROCED_MESTRE CAM ON(CPCD=CECP)
INNER JOIN ESPECIFICA_PROCEDCONV_DETALHE on (EPPC=CEPC)
INNER JOIN PROCEDIMENTO ON (PCCD=CEPC)
INNER JOIN PRESTADOR ON (PRCD=CPPR)
INNER JOIN FATURA_DETALHE_AMB ON (F2AM=CPAM)
INNER JOIN FATURA_MESTRE_AMB ON (F1CD=F2F1)
INNER JOIN AMBULATORIO ON (AMCD=CPAM)
WHERE CEAM=CAM.CPAM AND EPPV=CETB AND CETA IN(10,12) AND F1CD=:FAT
GROUP BY F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB
INTO F1CD, F1CV, F1FF, F1RC, F1RP, F1CT, PRDS, CPPR, PCSB, VALORE, VALORC, CEQT, TOTAL DO BEGIN
IF (:AMTH = ´C´) THEN VALORC = (VALORE * CEQT);
IF (:AMTH = ´E´) THEN VALORC = (VALORE * CEQT);
END
SUSPEND;


GOSTEI 0
Fsflorencio

Fsflorencio

04/02/2005

O problema de retornar uma linha só, é pq o suspend está mal posicionado. Ele deve estar no begin end do for.


GOSTEI 0
Sremulador

Sremulador

04/02/2005

bem amigos até que quase deu certo porém eu quero que se ouver valor no item VALOC E VALOE então eles aparecam lado a lado mas o item amth impede pois ele separa mas eu tenho que ter ele para fazer a compracao do if como poderia fazer meu sql ficou assim

FOR SELECT PRDS, CPPR, PCSB, AMTH, SUM(CEVL * CEQT) as CEVL, SUM(CEVH * CEQT) AS CEVH, SUM ((CEFM + CEVH + CEVL) * (CEQT)) AS TOTAL FROM CONTA_AMB_PROCED
INNER JOIN CONTA_AMB_PROCED_MESTRE CAM ON(CPCD=CECP)
INNER JOIN ESPECIFICA_PROCEDCONV_DETALHE on (EPPC=CEPC)
INNER JOIN PROCEDIMENTO ON (PCCD=CEPC)
INNER JOIN PRESTADOR ON (PRCD=CPPR)
INNER JOIN FATURA_DETALHE_AMB ON (F2AM=CPAM)
INNER JOIN FATURA_MESTRE_AMB ON (F1CD=F2F1)
INNER JOIN AMBULATORIO ON (AMCD=CPAM)
WHERE CEAM=CAM.CPAM AND EPPV=CETB AND CETA IN(10,12) AND F1CD=:FAT
GROUP BY PRDS, CPPR, PCSB, AMTH
INTO PRDS, CPPR, PCSB, :AMTH, VALORC, VAL, TOTAL DO BEGIN
VALC = NULL;
VALE = NULL;
IF (:AMTH = ´C´) THEN VALC = VAL; ELSE
VALE = VAL;
SUSPEND;
END


GOSTEI 0
POSTAR