Performance ABAP
Performance ABAP
Arquitetura Client-Server
Ninhos de select
Select …. Endselect ao invés de comandos que recuperem do banco de dados todos os
registros de uma única vez
Select * ao invés de select com as colunas necessárias ao processamento
Select single sem chave completa especificada ao invés de Select up to 1 row
Selects genéricos, ou seja, onde a cláusula where não foi fortemente especificada, com
várias condições, visando restringir
Índices não utilizados
Falta de índices
Select em tabelas com alto número de registros utilizando cláusula where baseada em tela
de seleção onde o preenchimento não é obrigatório
Definição funcional falha
Grandes tabelas do sistema: BKPF, BSEG, EKKO, EKPO, VBAK, VBAB, MKPF, MSEG,
J_1BNFDOC, J_1BNFLIN, EKET, EKBZ.
Funções genéricas, como por exemplo CLAF_CLASSIFICATION_OF_OBJECTS
Premissa:
VBAK contém 1000 registros, sendo que cada registro contém 575 bytes.
Fato:
A comunicação entre o DB server e o Application server acontece em pacotes de 32.000 bytes,
dependendo da rede e equipamentos de comunicação utilizados.
Portanto:
1000 registros x 575 bytes = 575.000 bytes
575.000 bytes / 32.000 = 20 pacotes
20 pacotes: na verdade este número é um pouco mais alto (mais ou menos 24), uma vez que
informações administrativas são transferidas em cada transmissão, juntamente com os dados.
O exemplo acima tenta ilustrar que, se forem selecionadas apenas as colunas neces-
sárias, a transferência de dados será menor e, consequentemente, haverá uma redução
significativa no tempo de resposta.
Get VBAK
Get VBAK fields vbeln auart bname kunnr
O segundo comando é muito melhor que o primeiro. Porém, nem todos os logical database
suportam select em colunas. Para verificar se isso é possível, acesse a transação SE36,
coloque o nome do database no qual se deseja efetuar uma pesquisa e escolha a
opção: extras -> field selection.
Os seguintes comandos SQL produzem o mesmo resultado, mas cada um deles requer seu
próprio cursor uma vez que os comandos não são idênticos (verifique a ordem das colunas
após a palavra Select e na cláusula WHERE):
Ao invés use:
OBS.: A estrutura do logical database VAV (utilizado anteriormente) é VBAK – VBUK – VBKD –
VBPA.
Se uma tabela não é especificada via um cartão TABLES então o sistema automaticamente
recupera somente os campos chave para aquela tabela (aqui VBUK não está presente no
cartão tables, assim somente os campos chaves são recuperados pelo sistema).
Se uma tabela é especificada via TABLES, todas as colunas são recuperadas, mesmo se
nenhum campo daquela tabela é usado no programa (veja a tabela VBKD – somente o campo
ZTERM deveria ser impresso).
Para evitar ter todas as colunas selecionadas da tabela, insira um comando GET para aquela
tabela, especificando os campos que serão utilizados pelo programa posteriormente.
Vantagem em performance:
Select … exit. Endselect. = 150.000 ms
Select … up to 1 rows = 1.500 ms
2.6. Check inside Select …endselect.
Em caso de condições de checagens muito complexas poderia ser mais rápido obter dados do
banco de dados primeiramente. SQL Trace precisa ser usado para verificar qual método é o
mais rápido.
Endselect.
O sistema standard é distribuído sem um índice para o campo bname. A seleção acima irá
resultar numa varredura sequencial da tabela vbak. Isto não é aceitável num sistema em
produção. Criando um índice na tabela vbak para o campo bname irá resolver o problema
neste caso. Exceção: tabelas cuja buferização é full ou generic (neste caso não tem sentido
pois o primeiro acesso irá trazer todos os dados para a memória. Das próximas vezes, o
sistema busca do buffer e não do database – até que o dado mude novamente).
Ao invés use:
Select matnr sum( kwmeng ) meins into table <internal table>
From vbap where ….
Group by matnr meins.
O ganho em performance para o processamento de 10.000 registros:
Select + collect = 2.370.000 ms
Select sum …. Into table = 1.574.000 ms
OBS.: o group by não pode ser usado para tabelas pool e cluster.
Programas irão rodar de forma correta e bem na entrada em produção, todavia a performance
irá decrescer à medida que dados são adicionados diariamente.
Para analisar a qualidade da buferização de tabelas use a transação ST02, dê duplo click em
TABLES (generic key) e clique no pushbutton “buffered objects”.
Tipos de buferização:
a) full: resident buffer (100 %): o conteúdo de toda a tabela é carregado no buffer no primeiro
acesso realizado na tabela
b) generic: uma chave genérica (primeiros “n” campo chaves) é especificado quando da
criação da tabela, quando se mantém technical settings. Esta chave genérica divide o
conteúdo da tabela em chamadas áreas genéricas. Quando acessando qualquer dado com
uma deteminada/especificada chave genérica, toda a área genérica é carregada no buffer.
c) Partial (single record): somente registros únicos são lidos do banco de dados e
armazenados no buffer.
Quando bufferizar uma tabela ?
Para tabelas que são usadas repetidamente ou por vários programas, considere a
possibilidade de criar estruturas de dados no Data Dictionary (e abrí-las através do comando
TABLES) ao invés de definí-las dentro de programas individuais (através do comando DATA
…. ENDDATA).
Sobre estas circunstâncias, o uso de tabela interna através do Data Dictionary é preferível:
Use o comando FREE para liberar memória alocada a tabelas internas. Este comando deve
seguir o último comando para processamento do dado na tabela.
5.1. Quando estiver sendo manipuladas grandes tabelas é muito importante que seja
processada a maior quantidade possível de informação num primeiro momento e, se possível,
eliminar qualquer outra passagem nesta mesma tabela. Muitas vezes isso requer o uso de
tabelas internas. Cada situação deve ser analisada e avalidada, para ver qual o procedimento
correto a ser tomado: se armazenar o dado ou fazer novo acesso à tabela do Data Dictionary.
Considere as seguintes questões:
qual o tamanho da tabela original comparado ao subset que seria armazenado em uma
tabela interna ?
quanto espaço para armazenamento seria necessário para armazenar o dado em uma
tabela interna ?
Se o processamento precisar ocorrer somente uma vez (por exemplo, armazenar alguns
dados para posterior comparação), esteja certo que isso acontecerá fora de uma estrutura em
forma de looping (por exemplo, Select, Loop, Do), de forma que o processamento não seja
repetido desnecessariamente.
Dica: o operador IN consome muito tempo de máquina e não deveria ser usado em lugar do
operador EQ .
5.2. Expressões lógicas são avaliadas da esquerda para a direita. A avaliação termina quando
o resultado final foi estabelecido (eliminação ou inclusão completa). Todavia, quando se utiliza
os operadores AND ou OR (por exemplo, em IF, WHERE) o critério de eliminação mais comum
deve ocorrer primeiramente.
Exemplo:
Table: The following table is to be read with printing of Employees from ABC Company in
Georgia
5.4.1. Um índice suporta pesquisa a dados no banco de dados. Todas as tabelas standard
SAP possuem um índice primário, o qual consiste de campos chaves que o usuário define
quando da criação de uma tabela. Para os selects aonde a chave primária não pode ser
utilizada na cláusula WHERE, ou quando selects não são qualificados, o banco de dados
pesquisa a tabela inteira (executa uma varredura sequencial).
Geralmente, se uma condição inclui OR, o otimizador pára o processamento (e chama uma
varredura sequencial) tão logo o primeiro OR seja encontrado. A exceção possível é um OR
que propõe uma condição separada e única para avaliação.
Exemplo:
ZTABLE é definida com um índice secundário:
isto não usa o índice conforme esperado e provavelmente invoca uma varredura
sequencial da tabela baseada na chave primária
Quando se utiliza o comando SET UPDATE TASK LOCAL o servidor de aplicação passa a
executar o update (ou seja, não é criado uma outra LUW no servidor de DB) e este fica
esperando a resposta se tudo ocorreu OK.
Um SET UPDATE TASK LOCAL é suficiente para todo o processamento do commit ser
efetuado como local. Por isso, todos os updates da SAP procuram não utilizar o comando Set
update task local. O default é o SET UPDATE (em funções). Isso evita que a performance seja
degradada.
6. Comandos Select
Select * seleciona todas as colunas de uma tabela. É melhor sempre especificar as colunas,
pois em caso de tabelas com muitas colunas, prejudicará performance.
7.7. SELECT * FROM <tabela> WHERE <campo> eq <conteúdo>.
Lê todos os registros da tabela especificada onde o campo é igual ao conteúdo especificado.
O ideal é que se qualifique a cláusula WHERE tanto mais quanto seja possível. Atentar que
isso é válido para tabelas do tipo Pool e Transparent. Para Cluster, seguir as recomendações
dadas anteriormente.
7.9. SELECT * FROM <table> WHERE <table field> BETWEEN <field1> and <field2>.
Ex.: field1 = 100 e field2 = 500. Pega inclusive 100 e 500. Você trabalha com o range.
7.16. SELECT * FROM <table> FOR ALL ENTRIES IN <internal table> WHERE
campo1 = <conteúdo> and
campo2 = <conteúdo>
Defino uma tabela interna. Alimento os campos desta tabela interna. (move e append). No meu
select campo1 e campo2 serão os campos definidos e alimentados na tabela interna.
Esta é uma excelente solução quando se trabalha com grandes tabelas.
O select for all entries simula a funcionalidade join.
7.18. SELECT carrid MIN( price ) max( price ) INTO (carrid, minimum, maximum)
FROM sflight GROUP BY carrid.
(Todos os campos que eu quero que apareçam na minha lista eu preciso especificar após a
cláusula GROUP BY. Carrid, maximum e minimum são campos auxiliares. Se o nome do
database não é conhecido até runtime não se pode especificar a cláusula GROUP BY).
Performance não é tão boa (funções MIN, MAX, etc. geram uma varredura sequencial na
tabela).
OBS.: Select single * sempre com chave completa especificada. Particularidade do Abap/4.
Select * - procurar evitar. Informar as colunas que serão necessárias, apenas.
8. Dicas para otimização do código (no mercado é dada pouca importância)
- Use o comando FREE para liberar espaço em internal tables; Sempre usar os comandos
Clear / Refresh após o fim de um LOOP;
- Evite comparações num SELECT com campos numéricos versus campos alfanuméricos; o
sistema perde tempo para conversão;
- Testar SY-SUBRC após cada acesso ao banco de dados;
- O comando MOVE-CORRESPONDING é bom para tabelas pequenas. É interessante que
a tabela interna contenha os campos na sequência em que serão movimentados;
- Ao utilizar o comando CASE, codificar sempre a cláusula WHEN OTHERS;
- Sempre identifique se um SORT é ascending ou descending e especifique a cláusula
BY <fields>. Caso contrário, todos os campos serão classificados.
- Evitar lógicas do tipo IF not CPOA = CPOB. É mais claro codificar IF CPOA ne CPOB.
- Evitar construções do tipo:
SORT tabela1, SORT tabela2, SORT tabela3.
LOOP tabela1, LOOP tabela2, LOOP tabela3
Para cada SORT fazer o LOOP correspondente. Aí então iniciar novo
SORT e LOOP, e assim por diante.
- Campos chave devem ser sempre os primeiros campos da tabela. Assim, todos os demais
campos serão comprimidos;
- SELECT (para Transparent e Pool Tables): a cláusula WHERE deve conter,
preferencialmente, os campos chaves e demais campos que possam restringir a
pesquisa;
- SELECT (para Cluster Tables): só os campos chaves devem ser especificados na
cláusula WHERE. Os demais devem ser checados através do comando CHECK;
- O conhecimento do conteúdo dos dados de uma tabela pode auxiliar no momento da
codificação do comando select. O campo que ocorrer em número menor de vezes
deverá constar na cláusula where antes daquele que ocorre um número maior de
vezes, caso seja necessário satisfazer a ambas condições. Isso faz com que o
processamento seja mais ágil.
- Manuseio de tabelas: Estudar a possibilidade de manuseio em tabelas internas para
agilizar o processo. Analisar também o uso de comando select, sendo o que melhor se
adapte a situação em questão.
9. Ferramentas para auxliar os desenvolvedores
Existe um pushbutton chamado Tips and Tricks – Clicando-se nele poderá ser feita
comparação entre comandos Select (diferentes tipos). Dando double-click sobre um dos
exemplos você passará para outra tela, onde você visualizará a medida do tempo em
microsegundos de ambos, servindo de base de comparação.
Neste mesmo path, pode-se utilizar as facilidades do Runtime Analysis para verificar a
performance de seu programa. Ao final da execução você poderá acessar informações sobre o
seu programa (gráficos, acesso a tabelas, etc). Para tanto clique o pushbutton ANALYSE, que
somente aparecerá depois que for informado o nome do programa e/ou transação e clicado
execute.
O SQL Trace (transação ST05) é outra facilidade que pode ser utilizada para trilhar a lógica
de sua aplicação e verificar possíveis pontos de correção. Você poderá visualizar os
comandos de acesso a banco de dados utilizados, obter informações sobre um comando
específico, visualizar os índices que estão sendo utilizados (ver tópico 5.3 sobre como utilizar
o SQL Trace).
O Extended Program Check é outra facilidade que deve ser empregada visando manter o
seu código o mais correto possível. Nesta opção você poderá selecionar os ítens que você
deseja que sejam checados e o sistema apontará o seu parecer. Para tanto basta clicar os
ítens e o pushbutton PERFORM CHECK Selecionando uma linha você poderá ver os
detalhes, bem como posicionando o cursor em uma linha e clicando o pushbutton DISPLAY
ALL CHANGES.
10. Interfaces Batch ou Conversões:
Segundo a documentação da SAP, existem três métodos para conversão: Direct input, Call
transaction e o Batch Input.
Direct Input: é um dos métodos para transferência de dados do sistema legado para o
sistema R/3. É considerado o método mais rápido. Um arquivo sequencial com dados é
gerado como um arquivo texto para processamento por alguns function modules especiais.
Estas funções executam todas as checagens normais para garantir a integridade de dados.
Quando os registros são processados com sucesso, eles são gravados diretamente nas
correspondentes tabelas do banco de dados da aplicação. Na ocorrência de erros, os
dados errados são passados para uma rotina de manuseio de exceção. O gargalo
associado com o processamento do dialog e update são eliminados neste caso. Para todas
as necessidades de transferência de dados, especialmente com transações de alto
volume, o direct input é o método mais indicado. Nota: este método deveria ser usado em
todas as situações nas quais funções de aplicação utilizando esta tecnologia existam.
AVALIAÇÃO:
Sempre execute alguns testes dentro do processo de transferência de dados e avalie qual
é o método mais apropriado para uso, dado o volume de dados, tamanho, recursos e
performance do sistema.
Todos os fatores sendo iguais, o método Direct Input deve ser usado em todos os casos
em que tais funções estejam disponíveis ou novas funções para transferência de dados
precisem ser desenvolvidas.
Para escolher entre o Call Transaction e o Batch-Iput, sempre use o Call Transaction
primeiro e manuseie as exceções então através do método de batch-input. Esta estratégia
é altamente recomendada em implementação de soluções de programação para
transferência de dados com sistemas legados.
11. Estudo de Caso – Cliente XYZ
(Parte do relatório de Quality Assurance da Fase III)
Dentro do escopo do XYZ seria necessário o desenvolvimento dos seguintes tipos de programa:
. Conversões
. Reports
. Formulários (SapScript)
. Interfaces
Obs.: exclui-se de nossa análise todos os programas de interface que encontram-se em fase de
desenvolvimento.
Alguns dados:
. Total de interfaces : 40
. Status : 03 em desenvolvimento
02 não tiveram desenvolvimento ABAP
35 estão concluídas
. Programas selecionados : ZIFIT002, ZIFIT006, ZLUIZ001 (antigo ZIMMT001)
ZIMMT006, ZIMMT010, ZIPMR001
1. É de extrema importância que, além dos testes individuais, sejam realizados testes com massa
de dados real de produção, visando reproduzir um ambiente real durante a fase de execução
das interfaces, com o objetivo de minimizar/eliminar problemas com performance;
2. Os testes devem englobar todas as condições lógicas possíveis, e até mesmo condições de
erro. Não existe esquema de “stress-test” (com grande volume de dados). A massa de dados
não deve ser gerado pelos desenvolvedores;
1. Na amostragem analisada foi constatado que o manual de Padrões não foi seguido de forma
íntegra. Em alguns casos (como por exemplo na Nomenclatura definida para Funções)
constante no manual, a forma utilizada nos programas é muito mais clara que aquela
anteriormente definida. Aconselha-se alterar o manual de Padrões, citando a nova forma
utilizada. No caso da definição de data-elements, este padrão não foi seguido para as tabelas
analisadas. Isso também se aplica aos nomes definidos para as sessões de Batch-input
pesquisadas via SM35 na data de nossa visita. Estes pontos não tem implicações graves sobre
os programas, todavia somente vale a pena a criação de uma metodologia caso ela seja, de
fato, seguida, e que esta visa facilitar o trabalho de pesquisa/leitura/manutenção de programas
;
2. Ainda dentro do tópico metodologia alguns pontos deveriam estar sendo seguidos: são os
nomes de variáveis. Nem todos os programas obedecem este tópico de forma integral ou
parcial. Este item é muito importante, uma vez que facilita a leitura dos programas e futuras
manutenções por terceiros ou até mesmo pela equipe técnica do XYZ;
3. Uso de mensagens fixas ao invés de text-elements, uma vez que o R/3 aceita várias
linguagens e isto é definido em momento de logon no sistema.
1. Dentro da amostra selecionada foram encontrados erros que se repetiam. São eles:
a) Ninhos de select
b) Select * ao invés de select com suas respectivas colunas
c) Falta de condições na cláusula where para limitar o números de registros retornados através
do comando Select
d) Tabelas como BKPF, BSEG, EKKO, EKPO, VBAK, VBAB, MKPF, MSEG, J_1BNFDOC,
J_1BNFLIN devem possuir, tantos campos quanto possível para restringir a pesquisa e busca
de dados.
e) Uso da função CLAS_CLASSIFICATION_OF_OBJECTS com finalidades específicas
Em vários casos encontramos selects em tabelas grandes, como por exemplo, a BKPF, trazendo-
se todos os registros que atendessem a uma única condição (por exemplo, código da transação).
É de extrema importância que, em casos de tabelas grandes (tanto em termos de volume quanto
em termos de quantidade de colunas) sejam recuperadas apenas as informações necessárias ao
atendimento do propósito do programa (colunas e condições). Deve-se lembrar que, com o passar
do tempo, a quantidade de dados presentes nestas tabelas estará crescendo; em contrapartida,
haverá uma redução da performance caso o programa não esteja fazendo seleções adequadas.
Uma forma de se obter maior seleção é inserindo um delimitador do tipo DATA, campos que
estejam presentes não somente na tabela acessada mas também na próxima que se deseja
acessar.
Dentro do exemplo acima, em forma de um ninho de Selects, é feito um outro Select para a tabela
BSEG. Ou seja, para cada registro da BKPF será acessada a tabela BSEG. Esta mesma situação
pode aparece em vários níveis, o que resulta num caos em termos de performance, à medida que
temos a base de dados sendo acrescida.
Além das precauções anteriores, as quais devem ser aplicadas sempre que possível, vale a pena
mencionar que o uso de tabelas internas agiliza muito o processamento. Selects que, num único
comando, sejam responsáveis por acessar a tabela, fazer a seleção do range de dados
necessário, movimentar estes dados para uma tabela interna e gravar estes dados terão
performance superior à uma situação de Select … endselect e infinitamente superior a uma
situação de Select … endselect em ninho.
* O primeiro comando seleciona as 79 colunas da tabela bkpf através do campo TCODE que, além
de não pertencer à chave primária desta tabela, também é um critério muito amplo para pesquisa
em tabelas deste porte. Campos como company code, data, ano fiscal, entre outros, podem ser
fortes candidados a restringir a pesquisa.
* O segundo comando seleciona as 266 colunas da tabela bseg, onde os campos bukrs, belnr e
gjahr sejam iguais à tabela anterior. Como na tabela anterior não foi utilizado um critério de
seleção mais adequado, muitos registros serão retornados da bkpf e, consequentemente, para
cada um destes registros, serão retornados “n” registros da BSEG.
Select col1 col2 col3 … into table tab_bkpf from bkpf where <conditions>.
OBS.: O exemplo dado de seleção de colunas é válido. Porém, vale lembrar que não é possível
fazer select colunado de tabelas Cluster.
Algumas considerações:
a) Hard Code
Alguns programas foram desenvolvidos baseando-se apenas na configuração atual do sistema
R/3. Com isso, aparecem algumas checagens de forma fixa, por exemplo, checagens de centros
(campo werks), conta contábil, etc., o que invalida os programas caso seja alterada a
configuração.
Foi criada uma tabela para controle do processamento, visando controlar quais registros foram ou
não processados em caso de alguma interrupção. O objetivo é permitir reprocessamentos
parciais. Tendo em mente que as transações estão sendo chamadas via Call transaction, técnica
esta que possui um commit próprio, e que a atualização da tabela de controle está num outro
commit, poderá ocorrer situações onde a tabela de controle não representa exatamente o que
aconteceu.
Necessidades:
a) Stress-test
b) Testes integrados
Comentários/Recomendações:
O ponto mais crítico está associado ao tópico de performance. É necessário fazer revisão em
todos os programas de interface, visando detectar situações semelhantes à descrita anteriormente
e providenciar as adequações necessárias.
Outro ponto de fundamental importância se refere aos testes. A garantia do bom funcionamento do
programa e a minimização de problemas com performance somente ocorrerá caso seja realizado
testes com massa de dados real, ou seja, volumes próximos ao esperado em ambiente produtivo,
cobrindo as situações que possam ocorrer.
Restrições:
Caso ocorra a entrada em produção sem a alterações nos programas, a performance será
decrescente, à medida que as bases de dados forem crescendo. Também não se pode garantir
que todas as interfaces pseudo-online serão processadas e finalizadas dentro do tempo
estipulado (por exemplo, a cada 5 minutos, etc).
Parecer:
De uma forma geral pode-se dizer que o desenvovimento está bom, porém caso os programas
não sejam revisados e adequados, certamente ocorrerão problemas de performance após a
implantação.
QUADRO RESUMO DA SITUAÇÃO DO PROJETO DA XYZ
Tópico Status
Confecção de especificação técnica 1.
V
SITUAÇÃO ATUAL
Dentro do escopo da ABC seria necessário o desenvolvimento dos seguintes tipos de programa:
. Conversões
. Reports
. Formulários (SapScript)
. Interfaces
Devido a alguns problemas, que serão detalhados mais adiante, o cronograma inicial cuja
expectativa era conter apenas 26 gaps sofreu alterações em termos de volume de
desenvolvimentos e também um atraso, estando neste momento a maioria dos programas em fase
de desenvolvimento e/ou testes. Novos desenvolvimentos também foram incorporados ao projeto
(cerca de oito novos programas foram criados). Assim sendo, optou-se por fazer o QA sobre os
programas em 24.06.98, independente de não estarem concluídos, uma vez que em caso da
necessidade de efetuar algum tipo de correção, haveria ainda seis dias corridos antes da data de
implantação.
Dado a esta situação, ressalta-se também que o coordenador de ABAP (parceiro da SAP) ainda
não teve tempo hábil para fazer a revisão dos programas que foram desenvolvidos, verificando o
cumprimento de normas, padrões e situações cuja performance não fosse satisfatória, antes que
os programas fossem apresentados ao Quality Assurance da SAP. A grande preocupação, no
momento, é a confecção dos programas.
Essa situação de análise de programas em desenvolvimento é atípica, uma vez que nossa análise
deveria se basear apenas sobre os programas já concluídos e revisados pelo parceiro de
implementação, mas dada a situação, isso não foi possível.
Alguns dados (dados aproximados, uma vez que o cronograma do projeto e status não estavam
atualizados):
. Total de programas : 34
. Status
Obs.: Interfaces de Estoques e Livros Fiscais são indispensáveis para a data de implantação
(01.07.98), no mínimo. As demais devem ser disponibilizadas logo após, para uso no decorrer do
mês de julho.
3. SapScripts:
. Certificado de Qualidade : desenvolvido
. Certificado de Análise : desenvolvido
. Pedidos : em testes
. Cotações : em testes
. Requisições : não será desenvolvido
4. Relatórios:
. Relatório de Confirmação de ordem de processo (1 e 2): desenvolvido
. Relatório de produção diária e mensal : aguarda definição de uma das
interfaces para ser desenvolvido
. Relatório síntese de estoque : não será desenvolvido. Será
utilizado relatório standard do R/3.
5. Matchcodes:
.Lote na ordem de processo : será desenvolvido
. Ordens não liberadas : será desenvolvido
. Ordens não confirmadas : será desenvolvido
. Materiais por grupo de listas técnicas : desenvolvido
. Fornecedores CGC/CPF : desenvolvido
Obs.: Dos programas relacionados anteriormente, apenas os programas ZAPPR001 e 002 tinham
status concluído. Todos os programas foram analisados a partir de versões existentes no ambiente
de desenvolvimento da ABC.
3. É de extrema importância que, além dos testes individuais, sejam realizados testes com massa
de dados real de produção, visando reproduzir um ambiente real durante a fase de execução
das interfaces, com o objetivo de minimizar/eliminar problemas com performance. Na ABC não
estão sendo feitos testes com alto volume de dados. Isso acaba mascarando problemas que
podem vir a ocorrer no futuro, caso haja um aumento significativo nos dados;
4. Os testes devem englobar todas as condições lógicas possíveis, e até mesmo condições de
erro. Não existe esquema de “stress-test” (com grande volume de dados). A massa de dados
não deve ser gerado pelos desenvolvedores nesta etapa de testes finais, pré-produção.
4. Na amostragem analisada foi constatado que o manual de Padrões não foi seguido de forma
íntegra. Algumas das diferenças são demonstradas abaixo
2. Dentro da amostra selecionada foram encontrados erros que se repetiam. São eles:
f) Ninhos de select
g) Select * ao invés de select com suas respectivas colunas
h) Falta de mais condições na cláusula where para limitar o números de registros retornados
através do comando Select
i) Tabelas como BKPF, BSEG, EKKO, EKPO, VBAK, VBAB, MKPF, MSEG, J_1BNFDOC,
J_1BNFLIN devem possuir tantos campos quanto possível para restringir a pesquisa e busca
de dados
Em vários casos encontramos selects em tabelas grandes, como por exemplo, a BSEG, trazendo-
se todos os registros que atendessem a uma única condição. É de extrema importância que, em
casos de tabelas grandes (tanto em termos de volume quanto em termos de quantidade de
colunas) sejam recuperadas apenas as informações necessárias ao atendimento do propósito do
programa (colunas e condições). Deve-se lembrar que, com o passar do tempo, a quantidade de
dados presentes nestas tabelas estará crescendo; em contrapartida, haverá uma redução da
performance caso o programa não esteja fazendo seleções adequadas. Uma forma de se obter
maior seleção é inserindo um delimitador do tipo DATA, campos que estejam presentes não
somente na tabela acessada mas também na próxima que se deseja acessar, etc.
Num outro programa existe um ninho de Selects em três níveis. Para cada registro da tabela
J_1BNFDOC é feito um ou mais acessos na tabela J_1BNFLIN e um ou mais acessos na tabela
J_1BNFSTX. Ninhos como este, com o crescimento na base de dados, trará resultados
desfavoráveis à performance. Esta mesma situação se repete em outros programas.
Além das precauções anteriores, as quais devem ser sempre tomadas, vale a pena mencionar que
o uso de tabelas internas agiliza muito o processamento. Selects que, num único comando, seja
responsável por acessar a tabela, fazer a seleção do range de dados necessário, movimentar
estes dados para uma tabela interna e gravar estes dados terão performance superior à uma
situação de Select … endselect e infinitamente superior a uma situação de Select … endselect
em ninho.
Endselect.
* O primeiro comando seleciona as 79 colunas da tabela bkpf através do campo <condition> que
é um critério muito amplo para pesquisa em tabelas deste porte. Campos como company code,
data, ano fiscal, entre outros, podem ser fortes candidados a restringir a pesquisa.
* O segundo comando seleciona as 266 colunas da tabela bseg, onde os campos bukrs, belnr e
gjahr sejam iguais à tabela anterior. Como na tabela anterior não foi utilizado um critério de
seleção mais adequado, muitos registros serão retornados da bkpf e, consequentemente, para
cada um destes registros, serão retornados “n” registros da BSEG.
Select col1 col2 col3, … into table tab_bkpf from bkpf where <conditions>.
Algumas considerações:
Loop at tab01.
Select * from bseg where mblnr eq tab01-mblnr.
Move-corresponding tab01 to tab02.
Move-corresponding mseg to tab02.
Append tab02. Clear tab02.
Endselect.
Endloop.
O primeiro select faz um único acesso ao servidor de banco de dados, trazendo todos os dados
necessários de uma única vez. (OK)
O select * na tabela bseg está dentro de um loop. Ou seja, este comando estará trazendo todas as
colunas desta tabela, que é uma das maiores do sistema R/3. Será movimentado através do
comando move-corresponding os campos cujos nomes sejam semelhantes de tab01 e mseg. Este
comando não oferece boa performance (gasta tempo identificando a igualdade no nome dos
campos).
Alternativa: O loop na tab01 indica que, para cada registro da tab01 (tabela interna), será
acessado um registro na bseg. Então, seria melhor proceder conforme abaixo:
Select mblnr bldat budat into table tab01 from bkpf where <conditions>.
Ou seja, evitar select * trazendo somente os campos necessários e fazer um único acesso à
tabela BSEG, trazendo todos os registros importantes para o processamento. Colocar também
mais seleções, objetivando restringir a quantidade de dados trazidos no primeiro select para,
consequentemente, restringir a quantidade de dados trazidos no segundo select. Pode-se pensar
em trazer todos os dados da BSEG para a própria tab01, através de appending corresponding
fields os table …. .
Ver help online para maiores detalhes sobre os comandos, em caso de dúvidas.
Este recurso de “for all entries” baseado na tabela anterior pode ser usado sempre, principalmente
nos casos onde performance for um fator crítico. Normalmente, os casos de selects encadeados
em forma de ninhos podem usar tal facilidade com uma incrível melhoria na performance.
Exemplos de programas que selecionam todas as colunas das tabelas acessadas: ZAFII001,
ZAMMI002, ZAMMI003.
Exemplos de programas que não acessam, selecionam, movimentam e gravam num único
comando select: ZAFII001.
Necessidades:
c) Stress-test
d) Testes integrados
Comentários/Recomendações:
O ponto mais crítico está associado ao tópico de performance. É necessário fazer revisão em
todos os programas, visando detectar situações semelhantes à descrita anteriormente e
providenciar as adequações necessárias.
Outro ponto de fundamental importância se refere aos testes. A garantia do bom funcionamento do
programa e a minimização de problemas com performance após entrada em produção somente
ocorrerá caso seja realizado testes com massa de dados real, ou seja, volumes próximos ao
esperado em ambiente produtivo, cobrindo as situações que possam ocorrer.
Restrições:
Caso ocorra a entrada em produção sem a alterações nos programas, a performance será
decrescente, à medida que as bases de dados forem crescendo. Também não se pode garantir
que todas as interfaces pseudo-online serão processadas e finalizadas dentro do tempo
estipulado (por exemplo, a cada “x” minutos, etc).
A documentação dos programas deverá ser providenciada, mesmo que após entrada em
produção, visando facilitar trabalhos de manutenções futuras.
Testes com massas de dados real ou com alto volume de dados eliminam/minimizam os problemas
com performance. A entrada em produção, na maioria dos casos, não é comprometida. Porém,
após alguns meses, pode-se ter um decréscimo significativo na performance.
Obteve-se a informação que o material de Quality Assurance da Fase II apenas foi entregue à
equipe de desenvolvimento ABAP a cerca de uma semana atrás. Vale ressaltar que este material é
altamente técnico, e basicamente voltado à equipe do projeto ABAP. O fato da equipe não ter feito
a leitura deste material desde o início do projeto traz alguns pontos negativos. Estes só não foram
maiores dada a experiência da equipe em outros projetos. Mesmo assim, certas irregularidades
poderiam ter sido evitadas.
Parecer:
De uma forma geral pode-se dizer que o desenvovimento está bom, porém caso os programas
não sejam revisados e adequados, certamente ocorrerão problemas de performance após a
implantação.
Um ponto positivo é que todos os programas possuem lógica simples e fácil para manutenções
futuras, se houver necessidade.
3 . QUADRO RESUMO DA SITUAÇÃO DO PROJETO
Tópico Status
Confecção de especificação técnica 2.
V
Observação:
Valerá muito pouco todo este trabalho se a configuração da máquina não estiver correta. É
necessário que ocorra uma visita de basis se o problema de performance não está num
programa em específico, mas em vários.