2011-07-08 29 views
5

Version: 11.2.0.2.0Giá trị Pls_integer yêu cầu dung lượng "ít" hơn so với Số. Cách xác minh?

Tôi muốn xác minh sự khẳng định sau tôi đang đọc một lần nữa trong cuốn hướng dẫn:

Các PLS_INTEGER kiểu dữ liệu có những lợi thế hơn các SỐ kiểu dữ liệu và NUMBER phân nhóm:

PLS_INTEGER values require less storage. 

Tôi đang tìm kiếm các byte được sử dụng hiệu quả.

Tôi biết các loại dữ liệu có sẵn trong Oracle và các kiểu dữ liệu PL/SQL. tôi đọc lại các phần cụ thể trong tài liệu:

Oracle data types

PL/SQL data types

tôi đã xem xét một số chức năng hữu ích: visze, dump (và vân vân: chiều dài, lengthb). Tôi đã tìm kiếm ở đây và trong các diễn đàn/blog khác, và ngay cả khi nó có vẻ là một điều rõ ràng đã học được trong quá khứ, tôi hơi bị mắc kẹt.


giả thủ tục (chức năng visize tôi sẽ không hiển thị bất kỳ giá trị hợp lệ cho pls_integer vì lý do minh họa bởi Tony Andrews trong câu trả lời của ông dưới đây (lưu ý 13/07/11)

create or replace procedure TestSize 
(
    testPlsInteger in pls_integer 
    ,testNumber  in number 
) is 
    sizePlsInteger pls_integer; 
    sizeNumber  pls_integer; 
    FORMAT_DIM constant pls_integer := 15; 
begin 
    select vsize(testPlsInteger), vsize(testNumber) 
    into sizePlsInteger, sizeNumber 
    from dual; 

    dbms_output.put_line('number:' || rpad(testPlsInteger, FORMAT_DIM) 
         ||' PLS_INTEGER SIZE:' || rpad(sizePlsInteger, FORMAT_DIM) 
         || ' NUMBER SIZE:' || sizeNumber); 
end; 

thử nghiệm

begin 
    TestSize(2147483647, 2147483647); 
    TestSize(1, 1); 
    TestSize(1000000, 1000000); 
    TestSize(12345678, 12345678); 
end; 

Kết quả

number:2147483647  PLS_INTEGER SIZE:6    NUMBER SIZE:6 
number:1    PLS_INTEGER SIZE:2    NUMBER SIZE:2 
number:1000000   PLS_INTEGER SIZE:2    NUMBER SIZE:2 
number:12345678  PLS_INTEGER SIZE:5    NUMBER SIZE:5 

- >>>>>>>>> PHẦN MỚI THÊM 13/07/2011

Sau khi tài liệu:

The PLS_INTEGER data type has these advantages over the NUMBER data type and NUMBER subtypes: 
PLS_INTEGER values require less storage. 

The PLS_INTEGER data type stores signed integers in the range -2,147,483,648 through 2,147,483,647, represented in 32 bits. 
  • Tài liệu khẳng định "giá trị PLS_INTEGER đòi hỏi ít lưu trữ " không phải là luôn luôn đúng.

Điều này đúng là loại dữ liệu số nên yêu cầu nhiều không gian hơn pls_integer. Viết lại quy trình trước đó bằng cách sử dụng hằng số cho kích thước pls_integer (32 bit giống như tài liệu nói), chúng ta có thể thấy bên dưới không đúng.

Tôi cho rằng đó là do sự đại diện nội của kiểu dữ liệu "number"

  • Nhưng OP là "làm thế nào để xác minh"

Sử dụng "lớn "gợi ý được đưa ra bởi Tony Andrews và tải hai mảng khác nhau có kích thước khác nhau (pls_integer và số), có vẻ như:

  1. Sử dụng số khác nhau mà yêu cầu lưu trữ khác nhau/tương đương (đầu ra của thủ tục đề cập trước đây "TestSize")
  2. Sử dụng varray để thực hiện mảng trong pl/sql
  3. Kiểm tra chiều hướng khác nhau cho những mảng 10 000, 100 000
  4. Các mảng lớn gồm 100 000 số yêu cầu nhiều không gian hơn so với các số khác.

PS Rõ ràng, phương pháp này là không hoàn toàn chính xác (như Tony đã viết trong bài viết của ông) và va chạm với đầu ra của thủ tục giả của tôi "TestSize", việc quy định rằng phương pháp này để tính toán các con số kích thước trong "TestSize" (vsize cho số) là chính xác!

FInally, tôi hiếm khi sử dụng mảng hơn 100/200 thành phần trong mã sản xuất của mình, chỉ để tránh quá tải PGA. Và đối với các khía cạnh này, sự nghi ngờ vẫn còn!

Các nghiên cứu khác tôi phải làm để khám phá "oracle" này, đó là ngoài kiến ​​thức của tôi; nhưng vì lý do này tôi đã viết câu hỏi này! :-)


Thủ tục bằng cách sử dụng mới "Testsize" thủ tục.

Xác nhận tài liệu "Giá trị PLS_INTEGER yêu cầu ít hơn bộ nhớ " không phải lúc nào cũng đúng.

create or replace procedure TestSize 
(
    testNumber  in number 
) is 
    sizeNumber  pls_integer; 

    SIZE_PLS_INTEGER constant pls_integer:= 4; -- always 32 bits(4 bytes) 
    FORMAT_DIM constant pls_integer := 15; 
    FORMAT_MINOR constant varchar2(1) := '<'; 
    FORMAT_EQUAL constant varchar2(1) := '='; 

begin 
    select vsize(testNumber) 
    into sizeNumber 
    from dual; 

    dbms_output.put_line('number:' || rpad(testNumber, FORMAT_DIM) 
         ||' PLS_INTEGER SIZE:' 
         || case when (SIZE_PLS_INTEGER<sizeNumber) then 
            rpad(SIZE_PLS_INTEGER, FORMAT_DIM,FORMAT_MINOR) 
           when (SIZE_PLS_INTEGER=sizeNumber) then 
            rpad(SIZE_PLS_INTEGER, FORMAT_DIM,FORMAT_EQUAL) 
           else rpad(SIZE_PLS_INTEGER, FORMAT_DIM) 
          end 
         || ' NUMBER SIZE:' 
         || case when (sizeNumber<SIZE_PLS_INTEGER) then 
             rpad(sizeNumber,FORMAT_DIM,FORMAT_MINOR) 
           else rpad(sizeNumber,FORMAT_DIM) 
          end); 
end TestSize; 

thử nghiệm

begin 
    TestSize(2147483647); 
    TestSize(1); 
    TestSize(10); 
    TestSize(100); 
    TestSize(1000); 
    TestSize(1000); 
    TestSize(100000); 
    TestSize(1000000); 
    TestSize(10000000); 
    TestSize(10000000); 
    TestSize(100000000); 
    TestSize(1000000000); 
    TestSize(1000000000); 
    TestSize(90000000); 
    TestSize(9923); 
    TestSize(99232); 
    TestSize(555555); 
    TestSize(12345); 
    TestSize(1234); 
    TestSize(1000001); 
    TestSize(20000000000); 
    TestSize(12345678); 
    TestSize(12345678); 
end; 

Kết quả

number:2147483647  PLS_INTEGER SIZE:4<<<<<<<<<<<<<< NUMBER SIZE:6    
number:1    PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:10    PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:100    PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:1000   PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:1000   PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:100000   PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:1000000   PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:10000000  PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:10000000  PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:100000000  PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:1000000000  PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:1000000000  PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:90000000  PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:9923   PLS_INTEGER SIZE:4    NUMBER SIZE:3<<<<<<<<<<<<<< 
number:99232   PLS_INTEGER SIZE:4============== NUMBER SIZE:4    
number:555555   PLS_INTEGER SIZE:4============== NUMBER SIZE:4    
number:12345   PLS_INTEGER SIZE:4============== NUMBER SIZE:4    
number:1234   PLS_INTEGER SIZE:4    NUMBER SIZE:3<<<<<<<<<<<<<< 
number:1000001   PLS_INTEGER SIZE:4<<<<<<<<<<<<<< NUMBER SIZE:5    
number:20000000000  PLS_INTEGER SIZE:4    NUMBER SIZE:2<<<<<<<<<<<<<< 
number:12345678  PLS_INTEGER SIZE:4<<<<<<<<<<<<<< NUMBER SIZE:5    
number:12345678  PLS_INTEGER SIZE:4<<<<<<<<<<<<<< NUMBER SIZE:5    

  • Các OP là "làm thế nào để xác minh "

Sử dụng" lớn "gợi ý được đưa ra bởi ** Tony Andrews

thủ tục Dummy "TestSize2"

create or replace procedure testSize2 
(
    testNum  in pls_integer 
    ,maxDim  in pls_integer 
    ,secondsToWait in pls_integer 
) is 
    type TPlsIntegers is varray(100000) of pls_integer; 
    type TNumbers is varray(100000) of number; 
    pls  TPlsIntegers := TPlsIntegers(); 
    numbers TNumbers := TNumbers(); 

    MODULE  constant varchar2(20) := 'TestSize2'; 
    PLS_ACTION constant varchar2(20) := 'pls_integer'; 
    NUMBER_ACTION constant varchar2(20) := 'number'; 
    SEP   constant varchar2(3) := ' - '; 

begin 
    dbms_application_info.set_action(action_name => PLS_ACTION||SEP||testNum ||SEP||maxDim); 

    pls.extend(maxDim); 
    for cont in 1 .. maxDim 
    loop 
     pls(cont) := testNum; 
    end loop; 
    dbms_lock.sleep(seconds => secondsToWait); 

    -- check pga with query 
    dbms_application_info.set_action(action_name => NUMBER_ACTION||SEP||testNum ||SEP||maxDim); 
    numbers.extend(maxDim); 
    for cont in 1 .. maxDim 
    loop 
     numbers(cont) := testNum; 
    end loop; 

    -- check pga with query 
    DBMS_LOCK.sleep(secondsToWait); 
end; 

thử nghiệm

declare 
    MAX_TO_WAIT constant pls_integer := 3; 
    MODULE  constant varchar2(30) := 'testSize2'; 
begin 
    debug.disable; 
    dbms_application_info.set_module(MODULE, action_name => ''); 
    testSize2(testNum => 90000000, secondsToWait => MAX_TO_WAIT, maxDim => 100); 
    testSize2(testNum => 90000000, secondsToWait => MAX_TO_WAIT, maxDim => 10000); --10 000 
    testSize2(testNum => 90000000, secondsToWait => MAX_TO_WAIT, maxDim => 100000); --100 000  

    testSize2(testNum => 12345, secondsToWait => MAX_TO_WAIT, maxDim => 10000); --10 000  
    testSize2(testNum => 12345, secondsToWait => MAX_TO_WAIT, maxDim => 100000); --100 000 

    testSize2(testNum => 2147483647, secondsToWait => MAX_TO_WAIT, maxDim => 100); 
    testSize2(testNum => 2147483647, secondsToWait => MAX_TO_WAIT, maxDim => 10000); --10 000 
    testSize2(testNum => 2147483647, secondsToWait => MAX_TO_WAIT, maxDim => 100000); --100 000*\*\*/ 

    dbms_application_info.set_action(action_name => 'END'); 
end; 

Query để giám sát PGA

select vsst.sid || ',' || vses.serial# username, vsst.value,vses.MODULE,vses.ACTION 
from v$sesstat vsst, v$statname vstt, v$session vses 
where vstt.statistic# = vsst.statistic# 
and vsst.sid = vses.sid 
and vstt.name = 'session pga memory' 
and vses.username = 'HR' 
and vses.MODULE = 'testSize2' 

annoted Kết quả

          pls_integer  number  dif 
--           size  size  size 
-- n=90000000   DIM aRRAY= 100  528612  594148< DIF= 65536 
-- n=90000000   DIM aRRAY= 10000 725220  1118436< DIF= 393216 
-- n=90000000   DIM aRRAY= 100000 2101476  5771492> DIF= 3670016 

-- n=12345    DIM aRRAY= 10000 921828  1380580< DIF= 458752 
-- n=12345    DIM aRRAY= 100000 2101476  5771492> DIF= 3670016 

-- n=2147483647  DIM aRRAY= 100  790756  856292 < DIF= 65536 
-- n=2147483647  DIM aRRAY= 10000 921828  1380580< DIF= 458752 
-- n=2147483647  DIM aRRAY= 100000 2101476  5771492> DIF= 3670016 
+0

Mục mới được thêm vào 13/07/2011 – zep

Trả lời

8

Chức năng VSIZE sẽ không hiển thị bất kỳ sự khác biệt bởi vì nó là một chức năng quá tải mà có thể mất một số, ngày tháng hoặc giá trị VARCHAR2 chỉ (xem thông số kỹ thuật của SYS.STANDARD). Vì vậy, khi bạn chuyển cho nó giá trị PLS_INTEGER, giá trị đó được chuyển đổi hoàn toàn thành NUMBER trước tiên.

Các definition của PLS_INTEGER nói

Loại lưu trữ dữ liệu PLS_INTEGER số nguyên ký trong phạm vi -2147483648 qua 2,147,483,647, đại diện trong 32 bit.

Vì vậy, nó luôn luôn là 32 bit = 4 byte. Trong khi đó, như bạn thấy, các VSIZE() của một số có thể có nhiều hơn 4 byte:

SQL> select vsize(2147483647) v from dual; 

v 
- 
6 

Một cách để bạn có thể thấy sự khác biệt là nếu bạn chạy một số PL/SQL mà populates một mảng lớn trong số NUMBERS trong bộ nhớ và xem xét mức sử dụng PGA cho phiên của bạn trước một phiên. Sau đó lặp lại cho PLS_INTEGER. Bạn có thể lặp lại thử nghiệm với các giá trị nhỏ và lớn, v.v. (Nên biết trước: PGA được phân bổ trong khối của một kích thước nhất định, vì vậy đây sẽ không được hoàn toàn chính xác, nhưng một mảng đủ lớn có thể hiển thị bất kỳ sự khác biệt đáng kể.)

Theo dõi PGA sử dụng sử dụng một truy vấn như:

select vsst.sid||','||vses.serial# username, 
     vsst.value 
from v$sesstat vsst, v$statname vstt, v$session vses 
where vstt.statistic# = vsst.statistic# 
and vsst.sid = vses.sid 
and vstt.name = 'session pga memory' 
and vses.username = 'MYUSER'; 
+0

+1 Cảm ơn bạn. Có cách nào để xác minh kích thước của một pls_integer hoặc tôi phải chấp nhận 32 bit mà không nhìn thấy nó. – zep

+0

Cảm ơn bạn.Ok tôi đã nhìn thấy bản cập nhật, điều này có nghĩa là đôi khi PLS_INTEGER yêu cầu nhiều byte hơn NUMBER, giống như số 1? – zep

+1

Có, tôi nghĩ vậy - hãy xem bản cập nhật mới nhất ở trên để biết cách tiếp cận để thấy sự khác biệt. –

Các vấn đề liên quan