Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Por que não devo fazer todos os meus bytes VARCHAR2 32767 somente PL/SQL?


Parece que esta é uma das áreas em que a funcionalidade PL/SQL evoluiu ao longo das versões quando a Oracle implementou otimizações diferentes.

Observe que isso também significa que algumas das respostas listadas no OP também são específicas da versão, mesmo que não sejam explicitamente mencionadas nessas perguntas/respostas. Quando o tempo passar e o uso de versões mais antigas do Oracle terminar (eu sonhando acordado?) essas informações ficarão desatualizadas (pode levar décadas).

A conclusão acima é apoiada pela seguinte cotação do capítulo 12 Ajustando aplicativos PL/SQL para desempenho da Referência da Linguagem PL/SQL 11g R1 :

Esse problema não é mais mencionado em 11g R2 nem 12c R1 versão do documento. Isso está de acordo com a evolução do capítulo 3 Tipos de dados PL/SQL.

Resposta:

Desde 11gR2 não faz diferença para uso de memória ponto de vista para usar varchar2(10) ou varchar2(32767) . O compilador Oracle PL/SQL cuidará dos detalhes sujos para você de maneira otimizada!

Para versões anteriores a 11gR2, há um ponto de corte em que diferentes estratégias de gerenciamento de memória são usadas e isso está claramente documentado na Referência de linguagem PL/SQL de cada versão .

O acima só se aplica a variáveis ​​somente PL/SQL quando não há restrição de comprimento natural que possa ser derivada do domínio do problema. Se uma variável varchar2 representa um GTIN-14 então deve-se declarar isso como varchar2(14) .

Quando interfaces de variável PL/SQL com uma coluna de tabela usam %type -attribute, pois essa é a maneira de esforço zero para manter o código PL/SQL e a estrutura do banco de dados em sincronia.

Resultados do teste de memória:

Eu executo uma análise de memória no Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 com os seguintes resultados:
str_size iterations UGA   PGA
-------- ---------- ----- ------
10       100        65488 0
10       1000       65488 65536
10       10000      65488 655360
32767    100        65488 0
32767    1000       65488 65536
32767    10000      65488 655360

Como as alterações do PGA são idênticas e dependem apenas de iterations e não str_size Concluo que o tamanho declarado do varchar2 não importa. O teste pode ser muito ingênuo - comentários são bem-vindos!

O roteiro de teste:
-- plsql_memory is a convenience package wrapping sys.v_$mystat s and
-- sys.v_$statname tables written by Steven Feuerstein and available in the
-- code-zip file accompanying his book.

set verify off

define str_size=&1
define iterations=&2

declare
  type str_list_t is table of varchar2(&str_size);
begin
  plsql_memory.start_analysis;

  declare
    v_strs str_list_t := str_list_t();
  begin
    for i in 1 .. &iterations
    loop
      v_strs.extend;
      v_strs(i) := rpad(to_char(i), 10, to_char(i));
    end loop;
    plsql_memory.show_memory_usage;
  end;

end;
/

exit

Exemplo de execução de teste:
$ sqlplus -SL <CONNECT_STR> @memory-test.sql 32767 10000

Change in UGA memory: 65488 (Current = 1927304)
Change in PGA memory: 655360 (Current = 3572704)

PL/SQL procedure successfully completed.

$