Tag > performance
Patrocinado por
Patrocinado por Inetum

Passar tabelas internas por valor é bom

images/thumbnail.jpg - Thumbnail

Quando um método devolve um valor como RETURNING este é sempre passado por valor e não por referência. Muitas vezes faço métodos que devolvem tabelas internas, algumas bastante grandes. Mas sempre me preocupou a ideia de que, como está a ser devolvida por valor, o ABAP devolva uma cópia da tabela interna, algo que pode ter impacto na performance e na memória que o programa gasta.

Felizmente fiquei recentemente a saber que não é assim.

Índices secundários em tabelas internas

images/thumbnail.jpg - Thumbnail

Durante anos as tabelas internas eram declaradas assim:

DATA: itbl TYPE TABLE OF bkpf.

DELETE vs CLEAR vs REFRESH vs FREE

images/thumbnail.jpg - Thumbnail

DELETE CLEAR REFRESH FREE

São várias maneiras de limpar os dados de uma tabela interna. À partida parecem iguais. Mas não são.

Ensina o ABAP a fazer malabarismo

images/thumbnail.jpg - Thumbnail

O que podemos fazer quando as noites não são suficientes para os processamentos diários?

Usarás TRANSPORTING NO FIELDS

images/thumbnail.jpg - Thumbnail

Muitas vezes fazes READ TABLE itbl ou LOOP AT itbl apenas para verificar se um registo existe (CHECK SY-SUBRC = 0). Ora para isso, os dados do registo não são realmente necessários. Nestes casos usa sempre TRANSPORTING NO FIELDS. Assim evitas ter de declarar uma estrutura destino e o programa fica mais rápido porque não tem de perder tempo a copiar dados.

INNER JOIN vs FOR ALL ENTRIES vs RANGES artificiais

images/thumbnail.jpg - Thumbnail

Uma vez que as operações de dados estão muito mais optimizadas no servidor de base de dados do que no ABAP, é sempre preferível o primeiro. FOR ALL ENTRIES só deve ser usado quando não se conseguir fazer INNER JOIN (como com a BSEG por exemplo). Quando possível, usar RANGES artificiais é preferível a usar FOR ALL ENTRIES mas é preciso cuidado para não ultrapassar o limite do parser de SQL.

Não farás SELECT *

images/thumbnail.jpg - Thumbnail

Tenta seleccionar sempre apenas os campos que vais realmente usar. Escolher todos é um desperdício de recursos. Excepção feita ao uso das FM *_SINGLE_READ que, embora leiam os campos todos, fazem cache dos dados, sendo por isso ainda assim mais rápidos de usar quando usados múltiplas vezes com a mesma chave. Se queres apenas verificar que um registo existe, selecciona apenas um campo, e se possível aquele que estás a usar como critério, evitando assim declarares uma variável extra.

Usarás FIELD-SYMBOLs em vez de variáveis de estrutura

images/thumbnail.jpg - Thumbnail

READ TABLE itbl ASSIGNING é sempre mais rápido que READ TABLE itbl INTO wa. Além disso, quando precisares de alterar dados em registos de uma tabela interna, assim não precisas de usar o comando MODIFY nem da variável auxiliar que às vezes usas para guardar o SY-TABIX. A única situação em que uma variável de estrutura é aconselhada é quando queres adicionar linhas novas a uma tabela interna. Algumas pessoas defendem que as variáveis de estrutura devem ser usadas sempre que não se quiser alterar os dados da tabela interna.

SELECT dentro de SELECT

images/thumbnail.jpg - Thumbnail

Provavelmente por razões históricas, os programadores ABAP não exploram as possibilidades do SQL. Muitos há que em vez de usarem INNER JOINs, ainda julgam que é mais rápido fazer vários SELECTs para tabelas internas e depois trabalhar os dados em ABAP. Mas a verdade é que, mesmo que se haja excepções, a regra é: quanto menos acessos à base de dados, melhor a performance. E faz sentido porque, afinal, porque foram escritas explicitamente para isso, as bases de dados relacionais são muito mais peritas em processar dados relacionais do que um programa ABAP.

Mas claro que há coisas que, pela sua complexidade, não podem ser feitas com um simples INNER JOIN. Ainda assim, algumas dessas coisas podem ser feitas num único SELECT.

Com muitos campos evita INTO CORRESPONDING FIELDS

images/thumbnail.jpg - Thumbnail

Já avisei aqui que, em tabelas com muitos campos, é sempre de evitar fazer SELECT *, devendo-se sempre seleccionar explicitamente apenas os campos necessários.

Mas não avisei ainda que há ainda outra optimização que merece ser feita: evitar o INTO CORRESPONDING FIELDS OF TABLE.

SORTED em vez de STANDARD nas tabelas de cache

images/thumbnail.jpg - Thumbnail

Há bastante tempo atrás escrevi aqui um artigo demonstrando as vantagens de usar tabelas internas com índices definidos em vez de simples tabelas STANDARD. Confissão: é tal o hábito instalado que desde então, quase todas as tabelas internas que criei continuaram a ser STANDARD TABLE. É muito frequente criar tabelas internas para fazer cache de dados que sei que vou utilizar amiúde dentro de LOOPs para evitar fazer SELECT SINGLEs lá pelo meio.

Análises parciais na SE30

images/thumbnail.jpg - Thumbnail

Claro que já conheces a transacção SE30 (Análise de tempo de execução) e claro que a usas amiúde para analisar programas standard e descobrir nele tabelas, funções, BADIs e quejandos. Ora se fores como eu, manténs uma relação de amor-ódio com esta transacção: se por um lado a amas por graças a ela consegues ver as entranhas de um programa sem ter de fazer debug, por outro lado odeia-la porque normalmente a lista de entranhas costuma ter milhares de linhas e tornar-se ingerível.

LOOP ASSIGNING em vez de LOOP INTO

images/thumbnail.jpg - Thumbnail

No princípio era o INTO. Aliás, no princípio nem sequer era o INTO.

Soneca

images/thumbnail.jpg - Thumbnail

Volta não volta é preciso meter um programa a dormir. E como em quase tudo, há várias formas de o fazer, e umas formas são melhores do que outras. A forma mais standard de conseguir isto em ABAP é a seguinte: WAIT UP TO 10 SECONDS. A vantagem do WAIT UP TO N SECONDS é que o processo é libertado durante estes 10 segundos, ficando assim disponível para quem o quiser apanhar.

Partida... lagarta... fugida!

images/thumbnail.jpg - Thumbnail

Senhoras e senhores, meninos e meninas, a corrida está prestes a começar.

Introdução

Apresento-vos as 4 participantes. São 4 tabelas internas, de diferentes raças e credos, que se vão pelejar pelo título atlético do LOOP em velocidade. Aqui estão elas:

Concorrente 1: DATA: LT_ITEM TYPE TABLE Concorrente 2: DATA: LT_ITEM_HASHED TYPE HASHED TABLE Concorrente 3: DATA: LT_ITEM_SORTED TYPE SORTED TABLE Concorrente 4: DATA: LT_ITEM TYPE TABLE + INTO INDEX