Como medir o consumo de memória e de processador de uma instrução sql?

Firebird

31/05/2012

Boa tarde colegas da lista

SGBD Firebird 2.5

Estou testando 4 instruções sql escritas de formas distintas, mas que resolvem o mesmo problema (ojbetivo: otimização).

O IB Expert retorna o tempo de execução, exemplo:

------ Performance info ------
Prepare time = 0ms
Execute time = 32ms

E quanto ao tempo de execução todas estão retornando tempos praticamente iguais.

Mas gostaria de saber se existe alguma opção/ferramenta/log que medisse o consumo de memória e de processador de uma instrução sql.

Assim, além de levar em conta o desempenho do tempo de execução, poderia verificar qual instrução das 4 é mais econômica em relação ao consumo de memória e qual é mais econômica em relação ao consumo do processador.

Se bem que, o consumo do processador, deve estar diretamente relacionado ao tempo de execução. Mas quanto ao consumo de memória seria muito importante descobrir qual das 4 é mais econômica.

Se existir uma maneira ou n maneiras de obter estas informações, este conhecimento poderia ser aproveitado por todos demais colegas em n necessidades de otimização.

Agradeço antecipado qualquer ajuda.

Delmar
Delmar Observação)

Delmar Observação)

Curtidas 0

Respostas

Diego Lusa

Diego Lusa

31/05/2012

Olá Delmar, tudo bem?

Utilize as tabelas de sistema (prefixo MOM$) para recuperar informações de consumo de memória e I/O. (http://ibexpert.net/ibe/index.php?n=Doc.SystemObjects).

Quanto a melhorias de desempenho, dê atenção ao uso de índices aliados a querys com bons planos de execução.
GOSTEI 0
Delmar Observação)

Delmar Observação)

31/05/2012

Olá Diego, comigo tudo bem e obrigado por participar. Como estás?

Pergunta A)
Já que tocaste no desempenho, gostaria de saber se usar TABELAS DERIVADAS para reduzir o número de registros, supondo duas tabelas com cardinalidade 1 par N que precisam fazer join devido a normalização, ou seja, primeiro reduzir os registros em TABELAS DERIVADAS e só depois fazer o join, é uma boa técnica de otimização? (obs: se alguém souber da existência de artigos sobre otimização com TABELAS DERIVADAS (não sub-consultas) baseado no padrão SQL:2003 ou versão mais atual e, puder postar os links, agradeço. Pois só encontro artigos que abordam otimização nos tempos quando nem existia TABELAS DERIVADA, ou será, que sou o único *maluco* a querer inventar otimização com TABELAS DERIVADAS!!!).

Vou dar um exemplo
tabela DECONTEUDO com 99.705 registros
tabela DEFREQUENCIA 2.492.927 registros

Vamos desconsiderar o SELECT mais externo

Em ambas as SQLs abaixo eu reduzi o número de registros para 64 registros em uma TABELAS DERIVADA *C* no INNER JOIN a partir da tabela DECONTEUDO

E na segunda SQL eu reduzi também o número de registros para 2.062 registros em uma TABELAS DERIVADA *FM* a parir da tabela DEFREQUENCIA (com um SELECT mais interno)

assim, a primeira faz join processando 2.492.927 de frequencia com 64 registros de conteúdo
SELECT F.CODMATRICULA, LPAD(EXTRACT(DAY FROM F.DATA), 2, 0) || / || LPAD(EXTRACT(MONTH FROM F.DATA), 2, 0) || / || F.PERIODO AS DIAMESPERIODO, F.PRESENCA FROM
    (SELECT CODMATRICULA, CODDECONTEUDO, DATA, PRESENCA, C.PERIODO FROM DEFREQUENCIA
        INNER JOIN (SELECT CODIGO, PERIODO FROM DECONTEUDO WHERE CODMINISTRA = :PCODMINISTRA AND BIMESTRE = :PBIMESTRE AND DATA BETWEEN :PDATAINICIAL AND :PDATAFINAL) AS C ON DEFREQUENCIA.CODDECONTEUDO=C.CODIGO
        WHERE CODMINISTRA = :PCODMINISTRA AND DATA BETWEEN :PDATAINICIAL AND :PDATAFINAL) AS F


e a segunda faz join processando 2064 registros de frequencia com 64 registros de conteúdo
SELECT F.CODMATRICULA, LPAD(EXTRACT(DAY FROM F.DATA), 2, 0) || / || LPAD(EXTRACT(MONTH FROM F.DATA), 2, 0) || / || F.PERIODO AS DIAMESPERIODO, F.PRESENCA FROM
    (SELECT CODMATRICULA, CODDECONTEUDO, DATA, PRESENCA, C.PERIODO FROM
             (SELECT CODMATRICULA, CODDECONTEUDO, DATA, PRESENCA FROM DEFREQUENCIA WHERE CODMINISTRA = :PCODMINISTRA) FM
     INNER JOIN (SELECT CODIGO, PERIODO FROM DECONTEUDO WHERE CODMINISTRA = :PCODMINISTRA AND BIMESTRE = :PBIMESTRE AND DATA BETWEEN :PDATAINICIAL AND :PDATAFINAL) AS C ON FM.CODDECONTEUDO=C.CODIGO) AS F


Ambas executam um fetch all com os mesmos tempos em praticamente 100% das tentativas.

Foi por isso que eu queria saber qual é mais econômica em memória (ainda fiz outras 2 instruções sql diferentes para este mesmo caso).


Diego, quanto a índices, em 82 tabelas temos 343 índices (de chave primária, de campos únicos e de todas integridades referenciais (100% de integridade)).

Pegunta B)
Agora, quanto a planos, já ouvi falar, mas não sei se tem que colocar de forma explicita na instrução SQL. Sempre vejo, que após executar instruções sql no IBExpert, gera um plano.

E os planos abaixo é o que o IBExpert gera respectivamente na execução das instruções SQL deste exemplo:

Plan
PLAN JOIN (F DEFREQUENCIA INDEX (FK_DEFREQUENCIA_MINISTRA), F C DECONTEUDO INDEX (PK_DECONTEUDO))

------ Performance info ------
Prepare time = 0ms
Execute time = 47ms
Avg fetch time = 0,02 ms
Current memory = 9.113.872
Max memory = 9.353.416
Memory buffers = 2.048
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 14.593


Plan
PLAN JOIN (F FM DEFREQUENCIA INDEX (FK_DEFREQUENCIA_MINISTRA), F C DECONTEUDO INDEX (PK_DECONTEUDO))

------ Performance info ------
Prepare time = 0ms
Execute time = 47ms
Avg fetch time = 0,02 ms
Current memory = 9.113.928
Max memory = 9.353.416
Memory buffers = 2.048
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 14.593

No momento não tenho nem ideia como se faz planos e onde devo colocá-los.

Agora, se otimizar com TABELAS DERIVADAS não é uma *viagem minha*, creio que este tópico vai interessar para muitos.

Agradeço imensamente aos que puderem colaborar.

Abraço e bom fim de semana.

Delmar
Ajuricaba/RS



GOSTEI 0
POSTAR