<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>performance on Abapinho</title><link>https://abapinho.com/tags/performance/</link><description>Recent content in performance on Abapinho</description><generator>Hugo -- gohugo.io</generator><language>pt</language><copyright>&amp;copy;2009-2026 Nuno Godinho</copyright><lastBuildDate>Mon, 11 Jul 2016 09:00:21 +0000</lastBuildDate><atom:link href="https://abapinho.com/tags/performance/index.xml" rel="self" type="application/rss+xml"/><item><title>Passar tabelas internas por valor é bom</title><link>https://abapinho.com/2016/07/passar-tabelas-internas-valor-bom/</link><pubDate>Mon, 11 Jul 2016 09:00:21 +0000</pubDate><guid>https://abapinho.com/2016/07/passar-tabelas-internas-valor-bom/</guid><description>&lt;p>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.&lt;/p>
&lt;p>Felizmente fiquei recentemente a saber que não é assim.&lt;/p></description></item><item><title>Índices secundários em tabelas internas</title><link>https://abapinho.com/2016/01/indices-secundarios-em-tabelas-internas/</link><pubDate>Mon, 25 Jan 2016 09:00:47 +0000</pubDate><guid>https://abapinho.com/2016/01/indices-secundarios-em-tabelas-internas/</guid><description>&lt;p>Durante anos as tabelas internas eram declaradas assim:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:2;-o-tab-size:2;tab-size:2;">&lt;code class="language-ABAP" data-lang="ABAP">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#00f">DATA&lt;/span>: &lt;span style="color:#000">itbl&lt;/span> &lt;span style="color:#00f">TYPE TABLE OF&lt;/span> &lt;span style="color:#000">bkpf&lt;/span>.&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>DELETE vs CLEAR vs REFRESH vs FREE</title><link>https://abapinho.com/2015/07/delete-vs-clear-vs-refresh-vs-free/</link><pubDate>Mon, 27 Jul 2015 09:00:01 +0000</pubDate><guid>https://abapinho.com/2015/07/delete-vs-clear-vs-refresh-vs-free/</guid><description>&lt;p>DELETE
CLEAR
REFRESH
FREE&lt;/p>
&lt;p>São várias maneiras de limpar os dados de uma tabela interna.
À partida parecem iguais.
Mas não são.&lt;/p></description></item><item><title>Ensina o ABAP a fazer malabarismo</title><link>https://abapinho.com/2015/05/processamento-paralelo/</link><pubDate>Mon, 18 May 2015 09:00:13 +0000</pubDate><guid>https://abapinho.com/2015/05/processamento-paralelo/</guid><description>&lt;p>O que podemos fazer quando as noites não são suficientes para os processamentos diários?&lt;/p></description></item><item><title>Usarás TRANSPORTING NO FIELDS</title><link>https://abapinho.com/2015/03/usaras-transporting-no-fields/</link><pubDate>Mon, 09 Mar 2015 09:00:02 +0000</pubDate><guid>https://abapinho.com/2015/03/usaras-transporting-no-fields/</guid><description>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.</description></item><item><title>INNER JOIN vs FOR ALL ENTRIES vs RANGES artificiais</title><link>https://abapinho.com/2014/11/inner-join-vs-for-all-entries-vs-ranges-artificiais/</link><pubDate>Tue, 25 Nov 2014 09:00:13 +0000</pubDate><guid>https://abapinho.com/2014/11/inner-join-vs-for-all-entries-vs-ranges-artificiais/</guid><description>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.</description></item><item><title>Não farás SELECT *</title><link>https://abapinho.com/2014/09/nao-facas-select-asterisco/</link><pubDate>Thu, 04 Sep 2014 11:25:03 +0000</pubDate><guid>https://abapinho.com/2014/09/nao-facas-select-asterisco/</guid><description>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.</description></item><item><title>Usarás FIELD-SYMBOLs em vez de variáveis de estrutura</title><link>https://abapinho.com/2014/07/usaras-field-symbols-em-vez-de-variaveis-de-estrutura/</link><pubDate>Thu, 24 Jul 2014 09:00:50 +0000</pubDate><guid>https://abapinho.com/2014/07/usaras-field-symbols-em-vez-de-variaveis-de-estrutura/</guid><description>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.</description></item><item><title>SELECT dentro de SELECT</title><link>https://abapinho.com/2014/05/select-dentro-de-select/</link><pubDate>Mon, 26 May 2014 09:00:03 +0000</pubDate><guid>https://abapinho.com/2014/05/select-dentro-de-select/</guid><description>&lt;p>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.&lt;/p>
&lt;p>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.&lt;/p></description></item><item><title>Com muitos campos evita INTO CORRESPONDING FIELDS</title><link>https://abapinho.com/2013/06/into-corresponding-fields/</link><pubDate>Mon, 10 Jun 2013 09:00:27 +0000</pubDate><guid>https://abapinho.com/2013/06/into-corresponding-fields/</guid><description>&lt;p>Já avisei aqui que, em tabelas com muitos campos, é sempre de evitar fazer SELECT *, devendo-se sempre seleccionar explicitamente apenas os campos necessários.&lt;/p>
&lt;p>Mas não avisei ainda que há ainda outra optimização que merece ser feita: evitar o INTO CORRESPONDING FIELDS OF TABLE.&lt;/p></description></item><item><title>SORTED em vez de STANDARD nas tabelas de cache</title><link>https://abapinho.com/2013/04/sorted-em-vez-de-standard/</link><pubDate>Mon, 01 Apr 2013 16:11:22 +0000</pubDate><guid>https://abapinho.com/2013/04/sorted-em-vez-de-standard/</guid><description>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.</description></item><item><title>Análises parciais na SE30</title><link>https://abapinho.com/2011/11/se30-parciais/</link><pubDate>Mon, 28 Nov 2011 11:37:25 +0000</pubDate><guid>https://abapinho.com/2011/11/se30-parciais/</guid><description>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.</description></item><item><title>LOOP ASSIGNING em vez de LOOP INTO</title><link>https://abapinho.com/2011/07/assigning-vs-into/</link><pubDate>Sat, 02 Jul 2011 12:25:03 +0000</pubDate><guid>https://abapinho.com/2011/07/assigning-vs-into/</guid><description>&lt;p>No princípio era o INTO.
Aliás, no princípio nem sequer era o INTO.&lt;/p></description></item><item><title>Soneca</title><link>https://abapinho.com/2011/06/soneca/</link><pubDate>Fri, 17 Jun 2011 11:43:28 +0000</pubDate><guid>https://abapinho.com/2011/06/soneca/</guid><description>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.</description></item><item><title>Partida... lagarta... fugida!</title><link>https://abapinho.com/2011/05/corrida-de-tabelas/</link><pubDate>Tue, 24 May 2011 09:00:41 +0000</pubDate><guid>https://abapinho.com/2011/05/corrida-de-tabelas/</guid><description>&lt;p>Senhoras e senhores, meninos e meninas, a corrida está prestes a começar.&lt;/p>
&lt;p>&lt;strong>Introdução&lt;/strong>&lt;/p>
&lt;p>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:&lt;/p>
&lt;p>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&lt;/p></description></item><item><title>LOOP FROM INDEX</title><link>https://abapinho.com/2011/03/loop-from-index/</link><pubDate>Thu, 10 Mar 2011 12:15:12 +0000</pubDate><guid>https://abapinho.com/2011/03/loop-from-index/</guid><description>É muito fácil meter os pés pelas mãos no que toca a performance quando se manipula tabelas internas. Principalmente quando elas são assim a tender para o grandalhonas. É até comum que estes problemas só surjam passados uns meses, quando as tabelas tendem a crescer com o tempo.
Por exemplo, quando fazes loop a duas tabelas, uma de cabeçalhos e outra de itens, fazes assim?
LOOP AT itab1 ASSIGNING &amp;lt;fs1&amp;gt;. LOOP AT itab2 ASSGNING &amp;lt;fs2&amp;gt; WHERE field1 = &amp;lt;fs1&amp;gt;-field1.</description></item><item><title>SAT - A nova ferramenta de análise de execução</title><link>https://abapinho.com/2011/02/sat/</link><pubDate>Wed, 16 Feb 2011 14:31:40 +0000</pubDate><guid>https://abapinho.com/2011/02/sat/</guid><description>Desde pequenino que uso a transacção SE30 para duas coisas diferentes:
Analisar um programa que desconheço (normalmente standard) para saber que funções usa, que BADIs disponibiliza, etc;
Analisar um programa meu em busca de problemas de performance.
A verdade, nua e crua, é que a transacção SE30 é uma porcaria pegada. Extremamente limitada e inflexível, não dá jeito nenhum para qualquer análise mais complexa.
Aparentemente os senhores da SAP concordam e resolveram substitui-la pela fantástica nova ferramenta SAT - ABAP Runtime Analysis , em tudo mais sofisticada.</description></item><item><title>Macros - Velocidade de ponta</title><link>https://abapinho.com/2009/09/macros-velocidade-de-ponta/</link><pubDate>Wed, 16 Sep 2009 02:37:52 +0000</pubDate><guid>https://abapinho.com/2009/09/macros-velocidade-de-ponta/</guid><description>&lt;p>Normalmente quando há um pedaço de código que pretendemos reutilizar várias vezes, transformamo-lo numa sub-rotina que pode depois ser invocada repetidamente. Embora a SAP não saiba estruturar o seu próprio código, ainda assim, o ABAP, coitadinho, permite-o. E até disponibiliza várias alternativas para modularizar o código. Eu conto quatro alternativas que listo aqui, da mais rígida para a mais flácida: METHOD, FUNCTION, FORM, DEFINE. Se os 3 primeiros são já familiar de todos, o último - DEFINE - quase ninguém usa. O DEFINE permite definir macros em ABAP. E o que são macros? São sub-rotinas aparentes.&lt;/p>
&lt;p>Aparentes porquê?&lt;/p></description></item><item><title>READ TABLE blablabla TRANSPORTING NO FIELDS</title><link>https://abapinho.com/2009/08/transporting-no-fields/</link><pubDate>Thu, 20 Aug 2009 04:51:19 +0000</pubDate><guid>https://abapinho.com/2009/08/transporting-no-fields/</guid><description>Por vezes ao fazer READ TABLE a uma tabela interna queremos apenas verificar se um determinado registo existe, e não nos preocupamos com os dados retornados. Algo tipo:
READ TABLE lt_kna1 INTO wa_kna1 WITH KEY kunnr = l_kunnr. CHECK SY-SUBRC = 0. Ora já que a estrutura WA_KNA1 não vai ser necessária de qualquer forma, mais vale não a usar, usando antes a opção TRANSPORTING NO FIELDS:
READ TABLE lt_kna1 TRANSPORTING NO FIELDS WITH KEY kunnr = l_kunnr.</description></item></channel></rss>