Why shouldn't I make all my PL/SQL-only VARCHAR2 32767 bytes?

前端 未结 3 1968
天命终不由人
天命终不由人 2020-12-30 09:47

Or should I ?

(The title is inspired by Gary Myers\' comment in Why does Oracle varchar2 have a mandatory size as a definition parameter?)

Consider the follo

相关标签:
3条回答
  • 2020-12-30 10:31

    It looks like this is one of the areas where the PL/SQL functionality has evolved over releases when Oracle has implemented different optimizations.

    Note this also means some of the answers listed in the OP are also release specific even that is not explicitly mentioned in those questions/answers. When the time pass by and use of older Oracle releases ends (me daydreaming ?) that information will became outdated (might take decades thought).

    The conclusion above is backed with the following quote from chapter 12 Tuning PL/SQL Applications for Performance of PL/SQL Language Reference 11g R1:

    Declare VARCHAR2 Variables of 4000 or More Characters

    You might need to allocate large VARCHAR2 variables when you are not sure how big an expression result will be. You can conserve memory by declaring VARCHAR2 variables with large sizes, such as 32000, rather than estimating just a little on the high side, such as by specifying 256 or 1000. PL/SQL has an optimization that makes it easy to avoid overflow problems and still conserve memory. Specify a size of more than 4000 characters for the VARCHAR2 variable; PL/SQL waits until you assign the variable, then only allocates as much storage as needed.

    This issue is no longer mentioned in 11g R2 nor 12c R1 version of the document. This is in line with the evolution of the chapter 3 PL/SQL Datatypes.

    Answer:

    Since 11gR2 it makes no difference from memory use of point of view to use varchar2(10) or varchar2(32767). Oracle PL/SQL compiler will take care of the dirty details for you in an optimal fashion !

    For releases prior to 11gR2 there is a cutoff-point where different memory management strategies are used and this is clearly documented in each release's PL/SQL Language Reference.

    The above only applies to PL/SQL-only variables when there is no natural length restriction that can be derived from the problem domain. If a varchar2-variable represents a GTIN-14 then one should declare that as varchar2(14).

    When PL/SQL-variable interfaces with a table column use %type-attribute as that is the zero-effort way to keep you PL/SQL-code and database structure in sync.

    Memory test results:

    I run a memory analysis in Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 with the following results:

    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
    

    Because the PGA changes are identical and depend only on iterations and not str_size I conclude the varchar2 declared size doesn't matter. The test might be too naïve though - comments welcome !

    The test script:

    -- 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
    

    Test run example:

    $ 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.
    
    $
    
    0 讨论(0)
  • 2020-12-30 10:38

    I think the problem is the same as in any other piece of software: allocating too much memory will decrease performance and likeliness of failing due to the facts it has occupied all memory.

    In my opinion, use %type as much as possible since it prevents mistakes when changing data type or length, and makes clear what the origin is from that variable.

    0 讨论(0)
  • 2020-12-30 10:40

    Maybe it's because I came of age in the era when the most memory any system had was 48k and then, happy days, up to a full 64k. And it was not virtual, what you allocated is what you got (wyaiwyg) (WAY-WIG?). I see in a lot of younger programmers a tendency to be lazy in their design and hide design flaws by throwing more memory at it.

    If we get into the habit of just typing varchar2(MAX) whenever we define a string variable, we stop thinking about the length. But sometimes length matters. If we haven't already done so, as soon as we type the ( then we should stop and put some thought into how big it really needs to be. Does the size matter here? If so, what is a reasonable maximum (or minimum)? This forces us to look beyond the bytes and fields and indexes to the actual "thing" we are trying to work with. That is never a bad idea.

    Discipline is hard. We should be developing habits to enforce it whenever we can. Good data and code design is difficult by nature. There are tools and techniques we can use to make it a little easier, but we shouldn't be doing anything just because it is easier. That's the path to the Dark Side and it catches up to us sooner or later.

    0 讨论(0)
提交回复
热议问题