Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Sunil.

Asked: July 16, 2000 - 3:02 pm UTC

Last updated: October 07, 2009 - 3:28 pm UTC

Version: 8.0.5

Viewed 10K+ times! This question is

You Asked

Hi Tom ,

We are oracle server 8.0.5. and the number of concurrent users
are around 100. We are using siebel applications . when we query there is
lot of sorting around 400,000 records . Is it possible that we can have sort area
size more then 1 MB. say around 2 MB and can we have sort area retained size also 2 MB
If you can send me the answer I will really appericiate that.
Thanks
Sunil

We are not running mts Server. The OS is Sun Solaries 2.6.
We want the query should be fast . Even we don't have that much of space . If we
Increase the sort area size (Is it necessary that sort_area_size and sort_area_retained_size should be equal)

Thanks for the fast reply

Sunil


and Tom said...


Sure, you can set the sort_area_size to 2m. The sort_area_size will be dynamically allocated by the dedicated server at runtime when a sort is invoked and this setting will allow it to GROW upto 2m in size (it'll not go right there, this is more of an upper bound). After a sort is completed, we will shrink the ram allocated by the process back down to the sort_area_retained size.

It is common, and the reason we have the 2 settings, to have sort_area_retained_size set smaller then sort_area_size. Think of these as upper and lower bounds. We'll start your session with no sort memory allocated. As you do sorts -- we'll allow you to allocate UPTO sort_area_size bytes to sort in memory. When the individual sorts are complete -- we'll shrink that pool of memory back down to the retained size (so we don't have to allocate it again -- that memory can be used for other things now).

Make sure you have enough physical ram for all of this work else the system will start swapping and paging. Consider how many concurrent sorts you expect (multiply that by 2m and make sure you can support that). Consider also the retained size * 100 and make sure you can support that as well.

You might start with 2m sort area size and a retained that is some fraction of that (say 0.5 meg) and see how that goes for you.

Also, make sure you are currently doing LOTS of sorts to disk first (see if this is going to have any effect or is just a shot in the dark). Simply:

select * from v$sysstat where name like '%sort%';

will tell you that.

Rating

  (29 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

A reader, June 08, 2001 - 5:04 am UTC


Thanks

Olga, September 22, 2001 - 7:15 am UTC


Kiro, December 10, 2001 - 5:01 am UTC


Sort Area Size and Order By

Chenna, March 04, 2003 - 9:46 am UTC

Tom

One of my queries takes 30 seconds with out order by, but amazingly takes 2436 seconds with the order by.

A couple of times I got the 'Cannot extend temporary segment by 128M error'.


I want to understand whats going on here. When I include 'order by' in my query, it is waiting for space in temporary segment , is that what is happening?

What type of a wait is it, if I want to go into the v$ tables and determine if this kind of wait is occurring , how should I find out. Is there a way to find out details about the waits created by my specific session.

When I trace my session, where should I look for , for this kind of waits in the trace file?

Please discuss in detail.

Tom Kyte
March 04, 2003 - 6:24 pm UTC

does it really take 30 seconds (it seems every time I get this sort of question is it really that -- well, it took 30 seconds to get the first pagefull in toad -- they didn't wait for the LAST row to come back).

Sorting generally must get all rows -- then sort -- then return. I will guess you really are comparing the time to get the first row from each query -- and that is not comparable.


Show us a TKPROF of the two queries....


It is not "waiting" for space in temp, it is using it.

retained size?

A reader, March 12, 2003 - 5:35 pm UTC

Hi

I am not sure what's the use of sort_area_retained_size since the memory are not released back to the server, I mean once sort_area_size has been allocated to an session the pga wont shrink will it? What's the point of using sort_area_retained_size?

Also I have a question regarding very big sort_area_size, our senior DBAs set the sort_area_size parameter to 256MB in one of our 7.3.4 database I was kind of shocked but he argues that he had to set that to speed up direct sql loader processes, the index rebuild phase needed to speed up. I remember when I was wokring in another shop I did tests with setting sort_area_size from 16mb to 128mb (16, 32, 64 and 128) and the process took more or less the same so I told him that setting sort area bigger than 32mb shouldnt yield extra benefits he argues back that if that was the case why he see PGA uses up to 256MB (as sort_area_size) which made me wonder too! If Oracle can use the memory we set then why the process (was basically very big indexes rebuilds) I tested didnt get faster?

Tom Kyte
March 14, 2003 - 7:08 am UTC

well, you have to think about configurations as well.

shared server -- sort_area_retained in the UGA in the SGA. sort area size - in the PGA in the dedicated server.

But -- is the sort_area_size not returned to the OS in dedicated server mode? Yes and no I say. If you have allocated memory, and then are not using it -- the OS can and will page it out - releasing the real physical memory for use by other processes.

I cannot comment on why your test did not show what you expected. I would need to see the test. I can say there is a good chance that the larger sort area would be useful. I can say that if I was using parallel query to rebuild -- I might want it smaller.

SORT_AREA_SIZE

gene charles, March 14, 2003 - 12:24 pm UTC

Hi Tom - good practical info. I ran the select from v$sysstat and got good results:
memory 4806255
disk 2835
rows 7055256499.

How do I found out which sql is doing the sorts on disks?



Tom Kyte
March 15, 2003 - 8:28 am UTC

it is not tracked at the statement level -- you can find the sessions...

my sort_area_size test

A reader, March 14, 2003 - 5:03 pm UTC

Hi

I carried following test

table with 28 columns
composite primary key, 4 columns
number of rows 3000000

table occupies 600MB
index 160MB

oracle 8.1.7.4, Locally managed tablespace (autoallocate), Sun Solaris 8

script (I change sort_area_size for each test, 16MB, 32MB, 64MB, 128MB):

alter session set sort_area_size=16777216;
drop index X_PK;
set timing on
CREATE UNIQUE INDEX X_PK ON X(X1, X2, X3, X4);
set timing off

results:
16MB 6 minutes 32 secodns to build the index
32MB 6 minutes 30 seconds to build the index
64MB 6 minutes 42 seconds to build the index
128MB 6 minutes 22 seconds to build the index

Checked with PMAP and corresponding amount of heap memory (showed in pmap) used

Number of temporary extents used for all tests, around 250 (1mb extent, LMT)

Absolutely no difference!

Tom Kyte
March 15, 2003 - 9:00 am UTC

so that means that -- your "bottleneck" if any was not in any way related to using temp.

that is all that shows.

you actually have shown two important things:

o tuning blindly and using conventional wisdom to tune is silly.
o that Oracle actually used 16, 32, 64, 128 meg of ram (but obviously that was NOT the bottleneck)



hmm I dont understand then

A reader, March 15, 2003 - 9:16 am UTC

Hi

I tried the whole test again today with 1MB ~ 300MB sort_area_size, 1MB took like 9 minutes the others still take 6 minutes or so... Even the 300MB one takes that time, I dont understand this at all, I thought I am making the sorts occuring in the memory. I dont see what can be the bottleneck.

BTW My collegue told me he was told by one of his friends working in Oracle Support that the sort algorithm used by Oracle doesnt get give you better results even you set massive sort_area_size, true?!?!


PS: If I had enough RAM in my server I would have tried 800MB (table size + index size) sort_area_size! Well I do have 2GB Memory but there are other instances running so...

Tom Kyte
March 15, 2003 - 2:08 pm UTC

DISK, writing 600meg to DISK and if you are in archive log mode, writing another X hundred meg there. Just means you were not cpu/memory bound, you were IO bound -- you had more then enough of those other resources.

At some point, all you are measuring anymore is "how long does it take to write this stuff".

So, you've done what is always best to do -- benchmarch, find the sweet spot





sort area size for all session ?

A reader, March 16, 2003 - 11:29 pm UTC

Is the sort_area_size value valid for each session or is it the total for all sessions ?

Tom Kyte
March 17, 2003 - 8:53 am UTC

it is PER sort...

A single session may in fact have more than one sort going on at a time and in doing so may have N "sort area size" chunks of memory all going.

Did I misread the docs?

Mark A. Williams, March 17, 2003 - 9:10 am UTC

Tom:

Did I misread the docs on this one? "What?!?!", everyone says, "the documentation???"

Anyway, from the 9iR2 Reference Guide for sort_area_size:

Increasing SORT_AREA_SIZE size improves the efficiency of large sorts. Multiple allocations never occur. Only one memory area of SORT_AREA_SIZE exists for each user process at any time.

It was my understanding that multiple sort_area_retained_size areas may be allocated, but only one sort_area_size would be created. Is this correct?

Thanks,

Mark

Tom Kyte
March 17, 2003 - 10:02 am UTC

ok, uncle.

sort area retained size would be the more appropriate number here, if you negate the use of parallel query which does it by process or thread in child sessions.

RE: Did I misread the docs?

Mark A. Williams, March 17, 2003 - 10:04 am UTC

Tom:

select standard_text
from thanks
where subject = this_one;

- Mark

standard_text

A reader, June 03, 2003 - 1:22 pm UTC

Mark,

Just curious - what does your above lines(sql) mean to say ?


A reader, September 01, 2004 - 5:21 pm UTC

Tom,

Is it ok to have SORT_AREA_SIZE not equal to temp tablespace initial_extent in a 8.1.7 dmt? We have SORT_AREA_SIZE=65536 and initial & next extents are 2097152.

What are the consequences and could it be changed now in production? Similarily can init.ora parameters be changed in a production d/b? Thanks

Tom Kyte
September 01, 2004 - 8:40 pm UTC

sure -- it is OK, you would just be grabbing 2m for a sort of anything over 64k.

As long as that is OK with you, it is OK with everything -- and would cut down on the extent requests.


v$parameter has a set of columns that tell you if a parameter is modifiable system/session/etc.  

but for this, you would either change SAS

NUM                           : "612"
NAME                          : "sort_area_size"
TYPE                          : "3"
VALUE                         : "65536"
ISDEFAULT                     : "TRUE"
ISSES_MODIFIABLE              : "TRUE"
ISSYS_MODIFIABLE              : "DEFERRED"
ISMODIFIED                    : "FALSE"
ISADJUSTED                    : "FALSE"
DESCRIPTION                   : "size of in-memory sort work area"
UPDATE_COMMENT                : ""
-----------------

(it is modifiable only at the session level or at the system level "deferred"


ops$tkyte@ORA9IR2> alter system set sort_area_size = 64000 deferred;
 
System altered.


or you can rebuild temp -- create temporary tablespace.... and then alter your users to use the new temp and drop the old temp.


but 2m is fine -- I use 1m myself (for the extent size) with PGA_AGGREGATE_TARGET in 9i -- where I have no idea what the sort area size is...

beware of changing init.ora's in production -- be ready to change them back (eg: have some change mgmt in place so everyone knows what is going on, what has changed..) 

SORT AREA SIZE

PHANI, March 28, 2005 - 11:59 am UTC

THE ANSWERS TOM GIVE ARE AWESOME.ITS REALLY HELPFUL TO JR.DBA'S LIKE ME.I READ THESE DISCUSSIONS ALL THE TIME.

Thank You for Your Answers.

Santosh Hiremath, May 04, 2005 - 8:59 am UTC

Hi Tom,

Thanks for your Answers because these will contain working nature of almost every parameters, now i came to know about the differences between SORT_AREA_SIZE and SORT_AREA_RETAINED_SIZE.

When you set PGA_AGGREGATE_AREA then no need of setting these parameter, but still i want to know info about below mentioned parameters.

If you have time please clarify me
Why exactly this "CREATE_BITMAP_AREA_SIZE" AND "BITMAP_MERGE_AREA_SIZE"
parameter have to be configured. As for as i know that these are independent from those from which i have mentioned above then

-i want to know where exactly these are allocated.

-if not then tell me how exactly these are configured internally.

Please correct me if i am wrong
depending on the which type of opertion you are perfoming your work area(CURSOR) is going to aquire that much memory to excute its query.

Thanks and Regards,
Santosh BANGALORE-INDIA.


Tom Kyte
May 04, 2005 - 10:05 am UTC

<quote>
When you set PGA_AGGREGATE_AREA then no need of setting these parameter,
</quote>

Let me expand that:

if ( version = 9i )
then
if ( pga_aggregate_target is set and workarea_size_policy is auto )
then
if ( connection is dedicated server )
then
these parameters (sort area [retained] size) need not be set
else
they do need to be set, shared server uses sort area size
end if
else
they do need to be set
end if
elsif (version > 9i )
then
if ( pga_aggregate_target is set and workarea_size_policy is auto )
then
these parameters (sort area [retained] size) need not be set
else
they do need to be set
end if
end if




the _size parameters (sort, hash, bitmap) are all treated the same.

if you are using automatic pga sizing, they are dynamically allocated workareas that are sized based on the current load on the server.

if you are not, they are allocated in the PGA memory of the server process (except for the sort_area_retained_size which is allocated in the UGA memory which is in the PGA in dedicated server mode, and the SGA in shared server mode)



Clarification on Aggregate PGA Target

Kevin Taufner, October 12, 2005 - 11:21 am UTC

Tom,

Thanks for the clarification on the interactions of PGA Target. However, I would like to know what happens when:

PGA_AGGREGATE_TARGET is set
AND
WORKAREA_SIZE_POLICY = AUTO
AND
SORT_AREA_SIZE = xxxxx

Will the auto allocation over-ride the manual setting? Or would I need to make sure the value for SORT_AREA_SIZE is removed from the SPFile for the system to utilize auto-management??

Tom Kyte
October 12, 2005 - 2:18 pm UTC

version 9i:
shared server -> sort_area_size is used regardless.
dedicated server AND workarea = auto -> pga_aggregate_target is used
dedicated server AND workarea = manual -> sort_area_size is used

version 10g
workarea=auto -> pga_aggregate_target
workarea= manual -> sort_area_size


you need not remove the sort_area_size, and since sessions could set workarea to manual - you might just want to leave it in with YOUR default.

How to create index quickly?

A reader, December 01, 2006 - 2:03 am UTC

Tom,

I am trying to build index on my fact table which has ~200 million rows.

I searched the Net to find 'how to hasten the index building process', and this is what I found on one of the Oracle forums:

"One more thing that can speed the process a lot:

alter session set sort_area_size=209715200; (200MB)

This causes the index creation to use memory for sorting instead of going to the temp tablespace."

(source: </code> http://forums.oracle.com/forums/thread.jspa?threadID=323421 <code>

My question is: How would Oracle know that it has to sort_area_space and not temp tablespace to build the index?
Or, do I have to explicitly state in the Create Index statement:

CREATE INDEX idx ON t ( key1 )
TABLESPACE sort_area_size NOLOGGING;

Please help.

Thanks


Tom Kyte
December 01, 2006 - 5:31 am UTC

well, that advice may or may not do a thing for you - the poster needed to provide a lot more information.

it really depends on what sort of memory management you are using.

Now, with a 200million row table - and 200mb of sort area size allowed (assuming manual memory management) that just means Oracle will use 200mb of memory BEFORE IT STARTS writing to disk. It will not prevent it, it might - but it might not. If you needed 1gb of memory - it will (in this case) obviously not avoid the write to temp.

consider:

a) parallel
b) nologging (don't forget to backup)

and set your sort_area_size appropriately OR the pga_aggregate_target appropriately.

<quote src=Expert Oracle Database Architecture>
Manual PGA Memory Management
In manual PGA memory management, the parameters that will have the largest impact on the size of your PGA, outside of the memory allocated by your session for PL/SQL tables and other variables, will be as follows:
* SORT_AREA_SIZE: The total amount of RAM that will be used to sort information before swapping out to disk.
* SORT_AREA_RETAINED_SIZE: The amount of memory that will be used to hold sorted data after the sort is complete. That is, if SORT_AREA_SIZE was 512KB and SORT_AREA_RETAINED_SIZE was 256KB, then your server process would use up to 512KB of memory to sort data during the initial processing of the query. When the sort was complete, the sorting area would be “shrunk” down to 256KB, and any sorted data that did not fit in that 256KB would be written out to the temporary tablespace.
* HASH_AREA_SIZE: The amount of memory your server process would use to store hash tables in memory. These structures are used during a hash join, typically when joining a large set with another set. The smaller of the two sets would be hashed into memory and anything that didnÂ’t fit in the hash area region of memory would be stored in the temporary tablespace by the join key.
These parameters control the amount of space Oracle will use to sort or hash data before writing (swapping) it to disk, and how much of that memory segment will be retained after the sort is done. The SORT_AREA_SIZE-SORT_AREA_RETAINED_SIZE is generally allocated out of your PGA, and the SORT_AREA_RETAINED_SIZE will be in your UGA. You can discover your current usage of PGA and UGA memory and monitor its size by querying special Oracle V$ views, also referred to as dynamic performance views.

.......


Automatic PGA Memory Management
Starting with Oracle9i, Release 1, a new way to manage PGA memory was introduced that avoids using the SORT_AREA_SIZE, BITMAP_MERGE_AREA_SIZE, and HASH_AREA_SIZE Parameters. It was introduced to attempt to address a few issues:
* Ease of use: Much confusion surrounded how to set the proper *_AREA_SIZE parameters. There was also much confusion over how those parameters actually worked and how memory was allocated.
* Manual allocation was a “one-size-fits-all” method: Typically as the number of users running similar applications against a database went up, the amount of memory used for sorting/hashing went up linearly as well. If 10 concurrent users with a sort area size of 1MB used 10MB of memory, 100 concurrent users would probably use 100MB, 1,000 would probably use 1000MB, and so on. Unless the DBA was sitting at the console continually adjusting the sort/hash area size settings, everyone would pretty much use the same values all day long. Consider the previous example, where you saw for yourself how the physical I/O to temp decreased as the amount of RAM we allowed ourselves to use went up. If you run that example for yourself, you will almost certainly see a decrease in response time as the amount of RAM available for sorting increases. Manual allocation fixes the amount of memory to be used for sorting at a more or less constant number, regardless of how much memory is actually available. Automatic memory management allows us to use the memory when it is available; it dynamically adjusts the amount of memory we use based on the workload.
* Memory control: As a result of the previous point, it was hard, if not impossible, to keep the Oracle instance inside a “box” memory-wise. You could not control the amount of memory the instance was going to use, as you had no real control over the number of simultaneous sorts/hashes taking place. It was far too easy to use more real memory (actual physical free memory) than was available on the machine.
Enter automatic PGA memory management. Here, you first simply set up and size the SGA. The SGA is a fixed-size piece of memory, so you can very accurately see how big it is, and that will be its total size (until and if you change that). You then tell Oracle, “This is how much memory you should try to limit yourself across all workareas—a new umbrella term for the sorting and hashing areas you use.” Now, you could in theory take a machine with 2GB of physical memory and allocate 768MB of memory to the SGA and 768MB of memory to the PGA, leaving 512MB of memory for the OS and other processes. I say “in theory” because it doesn’t work exactly that cleanly, but it’s close. Before I discuss why that is true, we’ll take a look at how to set up automatic PGA memory management and turn it on.
The process to set this up involves deciding on the proper values for two instance initialization parameters, namely
* WORKAREA_SIZE_POLICY: This parameter may be set to either MANUAL, which will use the sort area and hash area size parameters to control the amount of memory allocated, or AUTO, in which case the amount of memory allocated will vary based on the current workload present in the database. The default and recommended value is AUTO.
* PGA_AGGREGATE_TARGET: This parameter controls how much memory the instance should allocate, in total, for all workareas used to sort/hash data. Its default value varies by version and may be set by various tools such as the DBCA. In general, if you are using automatic PGA memory management, you should explicitly set this parameter.
So, assuming that WORKAREA_SIZE_POLICY is set to AUTO, and PGA_AGGREGATE_TARGET has a nonzero value, you will be using the new automatic PGA memory management. You can “turn it on" in your session via the ALTER SESSION command or at the system level via the ALTER SESSION command.
Note Bear in mind the previously discussed caveat that in Oracle9i, shared server connections will not use automatic memory management; rather, they will use the SORT_AREA_SIZE and HASH_AREA_SIZE parameters to decide how much RAM to allocate for various operations. In Oracle 10g and up, automatic PGA memory management is available to both connection types. It is important to properly set the SORT_AREA_SIZE and HASH_AREA_SIZE parameters when using shared server connections with Oracle9i.
So, the entire goal of automatic PGA memory management is to maximize the use of RAM while at the same time not using more RAM than you want. Under manual memory management, this was virtually impossible goal to achieve. If you set SORT_AREA_SIZE to 10MB, when one user was performing a sort operation that user would use up to 10MB for the sort workarea. If 100 users were doing the same, they would use up to 1,000MB of memory. If you had 500MB of free memory, the single user performing a sort by himself could have used much more memory, and the 100 users should have used much less. That is what automatic PGA memory management was designed to do. Under a light workload, memory usage could be maximized as the load increases on the system, and as more users perform sort or hash operations, the amount of memory allocated to them would decrease—to obtain the goal of using all available RAM, but not attempting to use more than physically exists.
</quote>


A reader, December 03, 2006 - 2:05 pm UTC

All that "gyan" (Sanskrit for knowledge) took me some time to digest, but was extremely useful nonetheless.

Thanks again!

please suggest,

chitta, May 01, 2008 - 7:58 am UTC

Hi Tom
I had written a query to fetch data in csv format
See below,
select ap_inv_hdr.supp_code||'^'|| ap_inv_hdr.second_ref||'^'|| ap_inv_hdr.doc_num||'^'|| ap_inv_hdr.doc_date||'^'|| ap_inv_hdr.doc_date||'^'|| ap_inv_hdr.narration||'^'|| ap_inv_hdr.gross_amt||'^'|| ap_inv_hdr.gross_amt||'^'|| ap_inv_hdr.payable_amt||'^'|| ap_inv_hdr.discount_amt||'^'||
ap_inv_hdr.due_date||'^'|| ap_inv_hdr.due_date||'^'|| ap_inv_hdr.pmnt_terms_code||'^'|| ap_inv_hdr.base_date from ap_inv_hdr
,ap_inv_line,ap_pay_line,ap_dbcr_alloc_hdr
where ap_inv_hdr.doc_type_code='APINV'
and ap_inv_hdr.doc_num = ap_inv_line.doc_num
and ap_inv_hdr.doc_num not in (select ap_pay_line.doc_num from ap_inv_hdr,ap_dbcr_alloc_hdr,ap_pay_line
where ap_inv_hdr.doc_type_code = ap_pay_line.org_doc_type_code and ap_inv_hdr.doc_num = ap_pay_line.doc_num
and ap_inv_hdr.doc_type_code = ap_dbcr_alloc_hdr.org_doc_type_code And ap_inv_hdr.doc_num = ap_dbcr_alloc_hdr.org_doc_num)
and ap_inv_hdr.doc_type_code not in (select ap_dbcr_alloc_hdr.org_doc_type_code from ap_inv_hdr,ap_dbcr_alloc_hdr,ap_pay_line
where ap_inv_hdr.doc_type_code = ap_pay_line.org_doc_type_code and ap_inv_hdr.doc_num = ap_pay_line.doc_num
and ap_inv_hdr.doc_type_code = ap_dbcr_alloc_hdr.org_doc_type_code And ap_inv_hdr.doc_num = ap_dbcr_alloc_hdr.org_doc_num)
/
While running this query an getting temp tablespace out of space error, I incresead thrice then again I got the same error, secondly I increased sort_area_size parameter as well but no result,
Please advice me whether my query is correct.


Regs,
Chitta

Tom Kyte
May 01, 2008 - 10:14 am UTC

.... Please advice me whether my query is correct. ....


I fell out of my chair when I read that, ouch, that hurts.


How in the world am I supposed to tell you if your query is correct????????

Only you know the question you are trying to answer - ONLY YOU.


Now, I look at your query, after putting it into a format human beings can read and understand:

select ...
  from ap_inv_hdr ,ap_inv_line,ap_pay_line,ap_dbcr_alloc_hdr
 where ap_inv_hdr.doc_type_code='APINV'
   and ap_inv_hdr.doc_num = ap_inv_line.doc_num
   and ap_inv_hdr.doc_num not in    (select ap_pay_line.doc_num
      from ap_inv_hdr,ap_dbcr_alloc_hdr,ap_pay_line
     where ap_inv_hdr.doc_type_code = ap_pay_line.org_doc_type_code
       and ap_inv_hdr.doc_num = ap_pay_line.doc_num
       and ap_inv_hdr.doc_type_code = ap_dbcr_alloc_hdr.org_doc_type_code
       And ap_inv_hdr.doc_num = ap_dbcr_alloc_hdr.org_doc_num)
   and ap_inv_hdr.doc_type_code not in
   (select ap_dbcr_alloc_hdr.org_doc_type_code
      from ap_inv_hdr,ap_dbcr_alloc_hdr,ap_pay_line
     where ap_inv_hdr.doc_type_code = ap_pay_line.org_doc_type_code
       and ap_inv_hdr.doc_num = ap_pay_line.doc_num
       and ap_inv_hdr.doc_type_code = ap_dbcr_alloc_hdr.org_doc_type_code
       And ap_inv_hdr.doc_num = ap_dbcr_alloc_hdr.org_doc_num)
/



I see you have four tables:

  from ap_inv_hdr ,ap_inv_line,ap_pay_line,ap_dbcr_alloc_hdr


but you only inner join two of them:
where ap_inv_hdr.doc_type_code='APINV'
   and ap_inv_hdr.doc_num = ap_inv_line.doc_num


and you cartesian join the other two

ap_pay_line,ap_dbcr_alloc_hdr



you do understand that if ap_pay_line has say 10,000 records and ap_dbcr_alloc_hdr has 10,000 records, that cartesian join will result in

100,000,000 records


and if the join between "ap_inv_hdr.doc_num = ap_inv_line.doc_num" results in 10,000 records after the NOT IN's are processed, your result set would be

1,000,000,000,000 records


I sort of am DOUBTFUL that this is the query you intended to code - but you are the only one that can answer that...


chitta, May 02, 2008 - 1:56 am UTC

Oops...


First of all I would not be ask like this,
I am sorry am not professional sql Developer, am trying to be,
My criteria is I wan to select some records from table A and that Record should not be in table B anc C and should present in table D. and I have common column doc_num and doc_type in all table.
So I try to built a query which is not working for me.

Please advice

Regs,
Chitta

Tom Kyte
May 02, 2008 - 7:16 am UTC

read about "not in" and "in"

select * from A
where (columns) not in (select from b)
  and (columns) not in (select from c)
  and (columns) in (select from d)


A reader, May 02, 2008 - 7:33 am UTC

"I wan to select some records from table A and that Record should not be in table B
anc C and should present in table D. and I have common column doc_num and doc_type in all table."


create table a (doc_num number, doc_type varchar2(1));
create table b (doc_num number, doc_type varchar2(1));
create table c (doc_num number, doc_type varchar2(1));
create table d (doc_num number, doc_type varchar2(1));

insert into a ( doc_num, doc_type ) values (1, 'X'); 
insert into a ( doc_num, doc_type ) values (2, 'X'); 
insert into a ( doc_num, doc_type ) values (3, 'X'); 
insert into a ( doc_num, doc_type ) values (4, 'X'); 
insert into a ( doc_num, doc_type ) values (5, 'Y'); 
insert into a ( doc_num, doc_type ) values (6, 'X'); 
insert into a ( doc_num, doc_type ) values (7, 'X'); 
insert into a ( doc_num, doc_type ) values (8, 'X'); 
insert into a ( doc_num, doc_type ) values (9, 'X'); 
insert into a ( doc_num, doc_type ) values (10, 'X'); 
insert into b ( doc_num, doc_type ) values ( 2, 'X'); 
insert into b ( doc_num, doc_type ) values ( 3, 'X'); 
insert into c ( doc_num, doc_type ) values ( 4, 'X'); 
insert into d ( doc_num, doc_type ) values ( 1, 'X'); 
insert into d ( doc_num, doc_type ) values ( 2, 'X'); 
insert into d ( doc_num, doc_type ) values ( 3, 'X'); 
insert into d ( doc_num, doc_type ) values ( 4, 'X'); 
insert into d ( doc_num, doc_type ) values ( 5, 'X'); 
commit;

select a.* 
  from a, d
 where a.doc_num = d.doc_num
   and a.doc_type = d.doc_type
   and not exists
       (select 1 
       from b, c
          where ((b.doc_num = a.doc_num and b.doc_type = a.doc_type) 
             or  (c.doc_num = a.doc_num and c.doc_type = a.doc_type)));

DOC_NUM  DOC_TYPE
-------  --------
1        X

Tom Kyte
May 02, 2008 - 8:08 am UTC

preferring big bulky straightforward SQL, I'll stick with not in and in.

and - your implementation in general is not correct, it would have to be:

from a, (select distinct doc_num, doc_type from d) d


no one specified anything about the relationship between A and D - in cannot be simply rewritten as a join (and not in cannot simply be rewritten as not exists)

our two queries return radically different results given the same data.

We'd need to actually know a lot more to write the correct query here - hence my psuedo code and the statement "read about...."


I suppose

select * from A
where (columns) not in (select from b union all select from c)
  and (columns) in (select from d)


might have advantages, and if the columns are nullable - we might add a is not null in the union query (then it would be like the not exists)

Thanks

A reader, May 02, 2008 - 8:45 am UTC

"..and - your implementation in general is not correct, it would have to be: "

well spotted... thanks. Just checked the original query again, they need all records from header table and they are checking the data against child tables (which may have more records).

chitta, May 05, 2008 - 6:07 am UTC

Hi,
I had written my own query, which is satisfy my requirement,
select *
from tableA
where not exists (select 'x' from tableB where tableA.doc_num=tableB.doc_num
and tableA.doc_type=tableB.doc_type)
and not exists (select 'x' from tableC where tableA.doc_num=tableC.doc_num
and tableA.doc_type=tableC.doc_type)
and exists (select 'x' from tableD where tableA.doc_num=tableD.doc_num
and tableA.doc_type=tableD.doc_type)


any comment on the above query,
Regs,
Chitta
Tom Kyte
May 05, 2008 - 10:21 am UTC

we already conversed about the approaches above.

We've seen a not in, a not in with a union all, a discussion about nulls....

did you read through that.

sort_area_size and temporary tablespace

ronak, February 07, 2009 - 11:29 pm UTC

hi Tom,

we are setting the sort_area_size, which is a part of pga, will be used for sorting requirment of process. but at the same time we also have temporary tablespace for the same purpose.

so why two options, n which will be used when??
Tom Kyte
February 09, 2009 - 6:18 pm UTC

they are not for the same purpose.

the temporary tablespace will be used to swap the contents of PGA sort areas to disk in the even the PGA sort area is insufficient.

A temporary tablespace and PGA workareas work in conjunction with each other to sort data that would otherwise be unsortable if we were restricted to just memory.

why is the sort area in UGA for the shared server?

Naresh Bhandare, March 25, 2009 - 8:47 pm UTC

Hello Tom,

Can you please explain why sort area is in UGA for the shared server configuration?

It is clear that, e.g., successive SQL queries from a client can be processed by different server processes in shared server. However, a single SQL statement - will it be processed by the same server process? And if yes, then what prevents the sort area from being allocated in that shared server process's memory space for the duration of that SQL statement?

Thanks,
Naresh

Tom Kyte
March 30, 2009 - 2:47 pm UTC

I wrote (quote)

... shared server -- sort_area_retained in the UGA in the SGA. sort area size - in the PGA in the
dedicated server.
....

...
if you are not, they are allocated in the PGA memory of the server process (except for the
sort_area_retained_size which is allocated in the UGA memory which is in the PGA in dedicated
server mode, and the SGA in shared server mode)
....

...
The SORT_AREA_SIZE-SORT_AREA_RETAINED_SIZE is generally allocated out of your PGA, and the
SORT_AREA_RETAINED_SIZE will be in your UGA.
.....

I never said the sort area was in the UGA.

sort area retained size, is the amount of memory your session keeps rows in memory, your SESSION needs these rows, they have to be in memory you always have access to.

In shared server, you get the server for a CALL - a call is "open query", "fetch a row from query", "fetch another row from query", "close query" and so on. You might use 50 different shared servers to process a single select statement.

Large sort-area-size

Praveen, April 28, 2009 - 8:31 am UTC

(1) The statement Id=5 (SORT ORDER BY) has used a temp space of 33M. But the SORT AREA SIZE is currently set to 2M only. Would it be a good practice to increase the sort area size to as high a value as 33M to improve the sort performance. Total number of records in the tables is less than a million.

(2) The statement Id=5 (SORT ORDER BY) has used a temp space of 33M. When you see the query, the ORDER BY is performed on the resultset returned by the sub-query, which is zero records. Why oracle is still using the temp space and try to sort "no-records"?

(3) I'm a bit bewildered by seeing the number 100 in "Rows" column of statement Id=0. The query has returned no rows. And the final SELECT operation returned 100 rows. How?



SQL>
SQL> SELECT r.*
  2    FROM (SELECT A.*, ROWNUM rn
  3            FROM (SELECT   x.*
  4                      FROM (
      :
      :
      /***<<A complex sub-query goes here.>>***/
      :
      :
      ) x
 66                  ORDER BY x.Report_Date DESC) A
 67           WHERE ROWNUM < 101) r
 68   WHERE rn > 0;

no rows selected

Elapsed: 00:00:07.92

Execution Plan
----------------------------------------------------------
Plan hash value: 2227841478

-------------------------------------------------------------------------------------
| Id  | Operation                              | Rows  | Bytes |TempSpc| Cost (%CPU)|
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |   100 | 21500 |       |  4364   (1)|
|*  1 |  VIEW                                  |   100 | 21500 |       |  4364   (1)|
|*  2 |   COUNT STOPKEY                        |       |       |       |            |
|*  3 |    FILTER                              |       |       |       |            |
|   4 |     VIEW                               | 29555 |  6003K|       |  4312   (1)|
|   5 |      SORT ORDER BY                     | 29555 |  4848K|    33M|  4312   (1)|
|*  6 |       FILTER                           |       |       |       |            |
|*  7 |        HASH JOIN                       | 87811 |    14M|       |  1059   (3)|
|   8 |         TABLE ACCESS FULL              |  7844 |   145K|       |    14   (0)|
|*  9 |         TABLE ACCESS FULL              | 87856 |    12M|       |  1043   (3)|
|* 10 |        TABLE ACCESS BY GLOBAL INDEX    |     1 |     8 |       |     8   (0)|
                                      ROWID  
|* 11 |         INDEX RANGE SCAN               |     4 |       |       |     3   (0)|
|  12 |         NESTED LOOPS                   |     1 |    23 |       |     5   (0)|
|* 13 |          INDEX RANGE SCAN              |     3 |    27 |       |     3   (0)|
|* 14 |          TABLE ACCESS BY INDEX ROWID   |     1 |    14 |       |     1   (0)|
|* 15 |           INDEX UNIQUE SCAN            |     1 |       |       |     0   (0)|
|* 16 |           TABLE ACCESS BY GLOBAL INDEX |     1 |    16 |       |     4   (0)|
                                         ROWID
|* 17 |            INDEX RANGE SCAN            |     2 |       |       |     2   (0)|
|* 18 |            INDEX RANGE SCAN            |     1 |    14 |       |     3   (0)|
|* 19 |     TABLE ACCESS FULL                  |     2 |    40 |       |     2   (0)|
-------------------------------------------------------------------------------------


Statistics
----------------------------------------------------------
         15  recursive calls
          0  db block gets
    1965924  consistent gets
      41574  physical reads
          0  redo size
        528  bytes sent via SQL*Net to client
       3102  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          0  rows processed

SQL>


Tom Kyte
April 28, 2009 - 10:22 am UTC

... The statement Id=5 (SORT ORDER BY) has used a temp space of 33M. ...

No, rather, it is that step 5 WAS ESTIMATED TO NEED 33mb, *estimated*


and you did all of the work in memory:
          1  sorts (memory)
          0  sorts (disk)



... Why oracle is still using the temp space and
try to sort "no-records"?
...

we didn't, again - EXPLAIN PLAN shows the GUESS, did you see the guess of rows there?

... I'm a bit bewildered by seeing the number 100 in "Rows" column of statement
Id=0. The query has returned no rows. And the final SELECT operation returned
100 rows. How?
....

an explain plan - the optimization process in general - works with imperfect information and attempts to GUESS the number of rows each step will return. It will almost NEVER be 100% correct.

See
https://www.oracle.com/technetwork/issue-archive/2009/09-jan/o19asktom-086775.html
for more examples.

Re: Large sort area size

Praveen, April 28, 2009 - 12:29 pm UTC

Thanks, Tom

some help in understanding and resolving issue we are facing

jv, October 02, 2009 - 7:10 am UTC

Dear Tom,

good day to you. I need your help in understanding below statistics, for one of the delete statement the plan I got using dbms_xplan.display_cursor is

Query : DELETE FROM a WHERE NOT EXISTS (SELECT null FROM b WHERE
a.Key=b.Key)
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc|
-----------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | | | |
| 1 | DELETE | A | | | |
| 2 | MERGE JOIN ANTI | | 13402 | 353K| |
| 3 | INDEX FULL SCAN | PK_a | 229K| 5151K| |
|* 4 | SORT UNIQUE | | 215K| 843K| 5096K|
| 5 | INDEX FAST FULL SCAN| I_b | 215K| 843K| |
-----------------------------------------------------------------------------------

it displays 5096K in tempspc but using query on v$sessstat and v$statname I see that no sort used disk for this session.

Value Name
241 sorts (memory)
0 sorts (disk)
472 sorts (rows)

we are on 10g and workarea_size_policy is auto with sort_area_size = 65536, can you please suggest how do we approach to resolve the problem of this query taking time and also why tempspc shows value but there's no sorts on disk.

Table A has 229357 rows and table B has 215594 rows, column key in Table B is not null.

Your help on this is much appreciated.

Regards,
JV
Tom Kyte
October 07, 2009 - 3:28 pm UTC

you understand an explain is a generic 'guess' at what will happen.

The plan is saying "at run time, I believe I will find 215,000 rows which I want to sort. Given that I don't know how much PGA I'll be allocated when I run (it could be a lot, it could be a little) - I think I'll take it safe and estimate a small pga. Given a small pga (what is small? depends on your pga_aggregate target... small to you is different than small to me), I think I'll need 5mb of temp space.


Reality is saying "at run time, when we ran this either we found far fewer than 215,000 rows to process OR we got a good sized pga, we didn't need that temp space on disk (but we might have used that temp space in MEMORY)".

so, you might have used that tempspace, but not on disk
or, you didn't need that much tempspace

with auto workarea_size_policy and 10g - sort_area_size is not relevant, it is not used. We allocate sort workareas based on the pga_aggregate_target and the current system workload (more users, less sort space for you, less uses, more sort space for you)

looks like you have hash joins disabled? is that true?

you would use tkprof to see where something is spending its time, enable tracing with waits (dbms_monitor) and use tkprof to format the trace file

help awaited

JV, October 07, 2009 - 7:28 am UTC

Dear Tom,
good day to you, with reference to the above post, is the sort_area size a problem.

Thanks a lot for your time and help on this.

Regards,
JV