Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Jonathan.

Asked: March 16, 2001 - 8:28 am UTC

Last updated: May 23, 2011 - 11:46 am UTC

Version: 8.1.5

Viewed 1000+ times

You Asked

You told me recently :

"1) you have a partitioned table, this table has ENABLE ROW
MOVEMENT defined on it. If you update the partition key that
causes the row to become a member of another partition, a new
rowid will be assigned to it.

2) you have an index organized table. the rowid (really a
urowid at that point) is a function of the primary key value.
If you change the primary key, causing the row to move in the
index, the urowid will change.


I would suggest that you use the PRIMARY KEY of the table, not a
rowid. Over time there may be other cases where the rowid will
change."



In the first case you described this is caused by some user or administrator command. So the dba will be aware of this rowid modification. Am I right?

In the seconc case it's only for the index table and not the table itself. Is that it?

So apparently I will be able to know if there is a modification in the rowids by asking to the DBA.

Anyway is there a place where I can find this information (the modification of a data physical loction)?
in a system view, in the log via logminer?...



and Tom said...

No, if I create a partitioned table and enable row movement -- the rowid of any row can change at any time in response to a simple UPDATE from an application.

the rowids in a partitioned table with row movement are not static. An update will change them.


the DBA will NOT know if the rowids have changed.


On those two table types, you should not rely on a rowid remaining static. You should use a PRIMARY KEY in any case. You cannot get this information reliably from log miner, there is no view.


I would strongly encourage you to use the PRIMARY KEY. A rowid is effective only in a session.


Rating

  (34 ratings)

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

Comments

where should we put rowid's to use

A reader, September 25, 2001 - 9:57 am UTC

Recently I and my colleague had a conversation on use or rowid's. We were not very sure as to what is the exact use of rowid's

According to my colleague

"rowid is the fastest mechanism for accessing a row in a table, even faster than a primary key. To perform bulk deletes or updates, use rowid if at all possible. "

I disagree with him , because as the user keep inserting rows and deleting rows, the rowid can change , isnt it?, the only time we can use rowid , is may be when we have be delete all the rows, in which case we might as well truncate the table.

But your statement below "A rowid is effective
only in a session.", though it comes after a strong recommendation to use primary key, vindicates my colleagues stand that , when you select a group of rows in a cursor and delete them by rowid , it will be valid.

Kindly discuss this aspect, and beat the issue to death.

what do you acutally mean by 'A rowid is effective
only in a session'.






Tom Kyte
September 25, 2001 - 8:34 pm UTC

The way I would use a rowid would be like this.

At time T1 an application issues a query "select rowid r, a.* from a". This fetches the data and the rowid from the table.

At time T2 that application decides it would like to modify the "n'th" row it fetched. BEFORE it does this it will issue:

select *
from a
where rowid = :fetched_rowid
and c1 = :fetched_c1
and c2 = :fetched_c2
...
and cN = :fetched_cn
FOR UPDATE NOWAIT;

That is -- we go back and RE-READ the row using the OLD values (:fetched_c1...) and the rowid. The rowid gets it FAST and the rest just verify that between the time we opened our query and the time we decided we wanted to modify it -- the data did not change

If that select gets 0 rows -- someone changed the row, we cannot update it -- we would suffer from a LOST UPDATE if we did (an update that overwrites someone elses changes without ever looking at their changes).

If that select gets an ORA-00054, someone else has the row locked, we shouldn't even try to update it.

If that select returns a row -- the row was not changed and is now LOCKED by us (the update will not block).


This is, for example, what Oracle forms does for you automagically.

By across sessions I meant -- you should never store a rowid in a table. The rowid of a row can change in 8i (never used to be able to change prior to that). IOTs and PARTITIONED tables can have rowids change on your unexpectedly.

You did not say across sessions you said

A reader, September 25, 2001 - 9:38 pm UTC

'A rowid is effective only in a session'.

why?


Tom Kyte
September 25, 2001 - 9:42 pm UTC

Which is the inverse of across sessions. My point is you should use them in a session -- not across sessions.

Ok, let me rephrase....

when I said "only in a session" i mean you should not use them across sessions. you should never store a rowid in a table. The rowid of a row can change in 8i (never used to be able to change prior to that). IOTs and PARTITIONED tables can have rowids change on your unexpectedly.



You have substantiate and elaborate the below statemet

Joe, September 25, 2001 - 9:43 pm UTC

developers always believed the contrary


"The rowid of a row can change in 8i (never used to be able to change prior to that). "

Yes , they can change with IOT's etc, but they never used to before... are you sure..

when you update or delete a row, doesnt a rowid change.

( well, you might have to explain us some basics, about rowid's, what is it made off , and why it doesnt change)





Tom Kyte
September 26, 2001 - 8:43 am UTC

Well, I don't have to substantiate -- its a fact, in 8.0 and before a rowid was immutable, never changing. Belief in the contrary isn't relevant, the fact is the rowid -- once assigned to a row -- never changed.

When you DELETE a row, its rowid doesn't change by definition -- its deleted, gone, doesn't exist (it no longer has a rowid).

When you UPDATED a row, its rowid never USED to change (8.0 and before). The row might "migrate", but the rowid never changed (we left the head piece of the row where it used to be and just leave behind another pointer to the new location).

Starting with 8i and the ability to create secondary indexes on IOTS (causing their urowid to change if you update the primary key) and the ability to ENABLE ROW MOVEMENT in a partition table changed that rule.

I recommend the server concepts manual as the definitive source of data on what a rowid is, what it is made of.

See
</code> http://docs.oracle.com/docs/cd/A58617_01/server.804/a58227/ch5.htm#2848 <code>
and page up once to "rowids of row pieces". this shows in 8.0 the rowid did not change. they confuse the issue with "exp/imp" however since the act of IMPORTING means you are creating a new row -- it should be somewhat obvious that a new rowid will be assigned.

Well, now that you made me look it up -- I discover they did NOT update the concepts guide in 8i/9i to reflect that a rowid can change (same paragraph as in 8.0 is there). I'll file a bug on that one.



contradictory

ray, September 26, 2001 - 12:28 pm UTC

"I would strongly encourage you to use the PRIMARY KEY. A rowid is effective only in a session."

and then you say , that within a session you can use rowid, to do deletes and updates.

Can I do

Update t

set t.x =(select t1.y from t1
where t.rowid=t.rowid
and t1.z='blah')

This corerelated update will be much faster , because Iam using the rowid, aint this true.

I dont care if changes are being made in other sessions. When my process runs I update all the rows which meet a particular criteria.

Kindly clear this for us , because the use of rowid all these days , has been minimum, if it is beneficial why not use it.




Tom Kyte
September 26, 2001 - 2:02 pm UTC

It is not contradictory. I say "strongly encourage", "you can (if you want to)". One is advice (strongly encourage), the other a fact. I would recommend you use a primary key but you can use the rowid.


As for your update

update t set x = decode( z, 'blah', y, null );

would be the most efficient way to do that. It is 100% equivalent to your correlated subquery. I cannot think of a reason to self join like that by rowid in an update ever.



sorry , there was a typo in the sql

ray, September 26, 2001 - 2:16 pm UTC

Update t

set t.x =(select t1.y from t1
where t1.rowid=t.rowid
and t1.z='blah')

I guess using rowid, in this way would be much make the sql execute much faster then using the primary key to join t and t1.

What can be the reasons, or situations or possible disadvantages when we use the rowid


Tom Kyte
September 26, 2001 - 2:29 pm UTC

that won't work at all -- the rowid from t cannot be compared to the rowid in t1. That query won't update anything, rather it will get:

update t
*
ERROR at line 1:
ORA-01410: invalid ROWID

(well, there is ONE special case where the update WON'T get that error -- here is a challenge for everyone -- post the full example here of the above update succeeding (and T1 is NOT a view of T!!! that would be too easy) with the create's and all ;)



Response to challenge

Mark A. Williams, September 26, 2001 - 5:09 pm UTC

Tom:

How about something like this for your challenge?  It isn't pretty, but I think it shows what you were looking for...


SQL> disconnect
Disconnected from Oracle9i Enterprise Edition Release 9.0.1.1.0 - 64bit Production
With the Partitioning option
JServer Release 9.0.1.1.0 - Production

SQL> connect scott@o9it
Enter password:
Connected.

SQL> create cluster tom_test
  2  (deptno number);

Cluster created.

SQL> create table emp2
  2  (empno number primary key,
  3  deptno number not null)
  4  cluster tom_test (deptno);

Table created.

SQL> create table dept2
  2  (deptno number,
  3  dname varchar2(32))
  4  cluster tom_test (deptno);

Table created.

SQL> CREATE INDEX idx_tom_test ON CLUSTER tom_test;

Index created.

SQL> insert into emp2 values (1000, 100);

1 row created.

SQL> insert into dept2 values (100, 'Test Dept');

1 row created.

SQL> update emp2
  2  set emp2.deptno = (select dept2.deptno from dept2
  3                     where dept2.rowid = emp2.rowid
  4                     and dept2.dname = 'Test Dept');

1 row updated.

SQL>

- Mark 

Tom Kyte
September 26, 2001 - 6:22 pm UTC

Rats -- that was it. (anyone who read my book and the chapter on clusters should have been able to come up with that).

didn't think it would be answered so fast. That just proves that a rowid is unique to a TABLE -- not unique within a database. In that cluster -- the row int he EMP table and the DEPT table actually have the SAME rowid.

challenge

Mark A. Williams, September 26, 2001 - 6:33 pm UTC

Tom:

Don't think of it as being answered so fast... think of it as your book is excellent and I spend too much time on 'AskTom'. :)

- Mark

Paul Heely, December 27, 2002 - 3:27 pm UTC

Tom,
You said:
"Well, now that you made me look it up -- I discover they did NOT update the
concepts guide in 8i/9i to reflect that a rowid can change (same paragraph as in
8.0 is there). I'll file a bug on that one."

I looked on metalink for documentation about this being missing from the concepts manual, but could not find anyting. Is there a bug number or metalink doc that we can reference to document the incorrect information in the 9i concepts manual? I need to document this problem in some code that we have and an "official" Oracle document would be helpful

Thanks.
--
Paul

Tom Kyte
December 27, 2002 - 3:36 pm UTC

Not that I'm aware of -- although there is this page.... You could file a TAR with support to get a support note written up on the topic.

Example to show changing rowid.

Paul Heely, December 31, 2002 - 9:45 am UTC

Tom,
Do you have any sample code that will illustrate a rowid changing inside an IOT?

Thanks.
--
Paul

Tom Kyte
December 31, 2002 - 10:05 am UTC

ops$tkyte@ORA920> create table t (x int primary key ) organization index;

Table created.

ops$tkyte@ORA920>
ops$tkyte@ORA920> insert into t values ( 1 );

1 row created.

ops$tkyte@ORA920> select rowid from t;

ROWID
-----------------------------------------
*BAJAAQwCwQL+

ops$tkyte@ORA920> update t set x = 2;

1 row updated.

ops$tkyte@ORA920> select rowid from t;

ROWID
-----------------------------------------
*BAJAAQwCwQP+

 

Thanks!

Paul, December 31, 2002 - 10:28 am UTC

Thanks Tom.

My own attempts at showing this were WAY to complicated, and didn't work. Your's is perfect.

--
Paul


questions on rowid

Tanmoy Datta Choudhury, May 26, 2003 - 2:43 am UTC

hi tom ,

recently i have got one requirment to print the two table in sql as it is ...

like if my two table is t1 and t2 having one col each ..
t1 t2
2 5
6
1 0
3
and i have to print the two table in sql as it is

i wrote one query like this
select t1.col1,t2.col2 from t1,t2
where substr(t1.rowid,18,14)= substr(t2.rowid,18,14);

which gives me the desired output ..but m little bit confused here becos u see there is no join condition in the tables but using substring m joining..(as after examining the rowids of two tables i have got some common char in it ..not so efficient think i suppose but i couldnt get any other hints to solve the problem )will i get the same result in any case (except IOT,cluster and index ) ...
and one more thing ...

as i have gone through your articel on rowid here ...can i say like this ..

rowid will be unique in the database (except IOT,cluster and index issues )

waiting for your advice ..


Tom Kyte
May 26, 2003 - 9:39 am UTC

rowid is NOT UNIQUE in the database.
rowid is unique within a table


but in any case, I've no idea what you are really trying to do here -- but I can say that using rowid like that is a recipe for disaster.  Are you trying to just take each row from t1 and join it with some row from t2 and output?

ops$tkyte@ORA920> select * from t1;

         X
----------
         2
         1
         3

ops$tkyte@ORA920> select * from t2;

         X
----------
         5
         6
         0

ops$tkyte@ORA920> select        t1.x, t2.x
  2    from (select rownum r1, x from t1 ) t1,
  3         (select rownum r2, x from t2 ) t2
  4   where r1 = r2
  5  /

         X          X
---------- ----------
         2          5
         1          6
         3          0


Now, if t1 and t2 have different cardinalities -- you'll need to outer join them. 

Question

Christo Kutovsky, May 29, 2003 - 2:52 pm UTC

Is it possible to receive and "Invalid rowid" under any circumstance from the following statement:

delete from TAB where rowid in
(select Y.rowid from TAB x, TAB y
where Y.col1 = X.col1
and Y.col2 != X.col2
)

In our case, the table is HASH partioned.


Tom Kyte
May 29, 2003 - 4:37 pm UTC

it would appear not. but i'm guessing you have experienced otherwise?

Followup to Question - Christo Kutovsky

Jim, May 29, 2003 - 6:34 pm UTC

I'm going to say yes it is possible.

I remember replicating something similar
and it was due to a Bug with view merging,
am pretty sure it is in 8.1.7

I'll see if I can find out exactly what is was.
the fix was changing the value of an init.ora parameter
that controls complex view merging

Regards
Jim


Followup to Tom

Christo Kutrovsky, June 01, 2003 - 12:10 am UTC

It seems that yes. According to the developers, they've got this error in the application, and according to the logs it was this query.

Before saying that it's impossible I decided to check for sure.

It should not matter even if the table is partitioned and has row movement on ? After all it's 1 query and read consistency is guarenteed.


Tom Kyte
June 01, 2003 - 9:11 am UTC

it should not, I cannot think of the case where it would but I haven't tried too hard to simulate it.

The obvious solution would be to use a primary key rather then rowid.

Follow-up

Christo Kutrovsky, June 01, 2003 - 12:41 pm UTC

Yes, that's what we suggested.

We also did "analyze TABLE validate structure" on the table, and also
select count(*) from
(select 1 from TABLE where rowid in
(select rowid from TABLE)
)

just to verify for any possible inconsistencies.

It's either the wrong SQL statement or a misterious bug in Oracle 9.2.0.2 (Solaris).

P.S.
Jim, I appreciate your help.


Followup

Jim, June 01, 2003 - 11:24 pm UTC

Sorry still looking for my notes on this.
I remember it still occured even when there was no
explicit reference to rowid. It was all to do with
how Oracle was merging views

Constancy of ROWID within a session

B. Robinson, July 24, 2003 - 2:34 pm UTC

What are the conditions that will ensure in Oracle8i and 9i that a session will see the same ROWID for the same row even if it is updated?

So far the following have been noted:
1. It must not be a partitioned table
2. It must not be an index organized table
3. Deleting will lose the ROWID (i.e. if you insert it back with the same data expect a new ROWID)
4. Do not expect it to be the same for another session

What else is necessary to guarantee the ROWID will remain the same within a session? Or is it that there is no guarantee at all? Are the conditions different for 8i vs. 9i?

Thanks.

Tom Kyte
July 24, 2003 - 4:32 pm UTC

there are NONE......


#3 PRECLUDES that.

You need to run a query like:

select * from t where rowid = :r and PRIMARY_KEY = :pk;

to be sure it is the "same row"

Thanks ... but let me explain

B. Robinson, July 24, 2003 - 9:53 pm UTC

What I meant was -- are there some things that you can do and NOT do to guarantee that ROWID will be the same?

If I do updates on a table but don't violate any of the conditions 1-4 (ie. I DON'T delete, don't use IOT or partitions, etc.), will that guarantee that ROWID will be the same? If not, are there any other things that can be done to ensure it will remain the same within a session, while still allowing updates?

Basically, I am maintaining a large system developed over several years that makes use of ROWID in a number of places, and I need to analyze which areas of it are at immediate risk of producing erroneous results due to mutating ROWIDs (which wasn't an issue when the system was being developed on earlier versions of Oracle). If I can determine which conditions would make ROWID usage "safe", I can then prioritize any necessary changes and focus on the most shaky parts.

Tom Kyte
July 25, 2003 - 7:05 am UTC

the rowid will stay the same for a row as long as it exists if you do not enable row movement and you do not use IOT's



rowid

Reader, August 23, 2003 - 1:54 pm UTC

rowid is unique within a table not in the database is true because of extended rowid that includes objectid as a component in rowid. Is it right? Thanks.

Tom Kyte
August 23, 2003 - 6:25 pm UTC

no, even in version 7.3 (before extended rowids blah blah blah) rowid was unique in a TABLE, not in a DATABASE.

The rowid is applied to a table, not a database.

rowid

Reader, August 23, 2003 - 9:09 pm UTC

From the link,

</code> http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96540/sql_elements6a.htm#19762 <code>

'Usually, a rowid value uniquely identifies a row in the database. However, rows in different tables that are stored together in the same cluster can have the same rowid."

May be I am not interpreting your statement properly. I always thought rowid is unique to the database. Thanks.



Tom Kyte
August 23, 2003 - 9:35 pm UTC

it is not. it is unique in a table, not in a database.

clusters make this possible. it is easy to have two rows in the same database in different tables have the same rowid.


see
</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:433278366052 <code>

for an exmaple

uniqueness of rowid

Reader, August 24, 2003 - 6:38 pm UTC

tom, only for clusters, the rowid is unique within a table. However, for heap tables still rowid is uique within the database. Is it correct? Thanks.

Tom Kyte
August 24, 2003 - 9:09 pm UTC



does it really matter?

the bottom line is this "a rowid is unique in a table. it cannot be used to identify a table. any application that believes otherwise has a bug just waiting to happen. a rowid is unique in a table -- period"

that is might be unique across heap tables, or iots or whatever -- not really "relevant"

(but yes, across heaps, it'll be unique)

Helena Marková, August 25, 2003 - 8:10 am UTC


DML using rowid vs PK

A reader, September 09, 2003 - 5:08 am UTC

Hi

I am wondering when we use PL/SQL to make some DML changes to tables (for example using cursors) what is faster, using rowid in WHERE clause or the PRIMARY KEY?

Tom Kyte
September 09, 2003 - 11:38 am UTC



well, how did you get the rowid in the first place?

this is not an apples and oranges comparision at all.

Max rowid

Phil, September 24, 2003 - 6:01 am UTC

On the subject of rowid..and sorry if this is a basic question but

What exactly does max(rowid) mean , would it be the last updated/inserted row?

Regards
Phil

Tom Kyte
September 24, 2003 - 9:44 am UTC

no, it just means the biggest rowid in the table.

the biggest rowid could be the newest row in the table
it could be the oldest row
it could by any row in between.

nothing can be ascertained by "max(rowid)" other then "i've got the biggest rowid"

Rowid

Phil, September 24, 2003 - 10:29 am UTC

Thank you very much for that, as I had an asumpation that max(rowid) was actually very specific ie the last row updated/inserted.

In that case...and please forgive me for straying (as i thought max(rowid) would help here)

if I had a table of

account balance2 balance date
------- -------- ------------
1 200 01/Jan/2003
1 300 01/Jan/2003
1 -400 01/Jan/2003
2 500 01/Jan/2003

how can I get the last balance for the account, if it is a rolling balance. In the above table the balance for account 1 is currently -400.

I was under the impression (incorrectly) selecting the value with the max(rowid) would do the trick !

Thanks

Tom Kyte
September 24, 2003 - 12:13 pm UTC

select *
from ( select account, balance, balance_date, max(balance_date) over (partition by account) max_dt
from t )
where balance_date = max_dt;

is but one way....

if you need it just for an account:

select *
from ( select * from t where account = :x order by balance_date DESC )
where rownum = 1;

is another.

thank you

phil, September 24, 2003 - 12:25 pm UTC

regards
phil

phil, September 29, 2003 - 9:41 am UTC

Sorry to drag out, as this has now little to do with rowid, but would the query you provided not return all rows for account 1 as they all have the same date/time value ?

This seems to be happening for me. I am trying to make sure I get the last row that was inserted as this would be the last balance.

this is the query I am using:

select * from (
select account_fk,balance_date_time,booked_balance,available_balance,
max(a.balance_date_time) over (partition by account_fk) max_date
from accountbalance a
where account_fk in ( 1,2,3,4 )
) b
where balance_date_time = b.max_date

thanks

Tom Kyte
September 29, 2003 - 12:40 pm UTC

there is no such thing as "a last row inserted" unless you have some field there to tell you which row is "last".

I have to assume the DATE field would be the date of insertion, in which case, it gives you the last row "inserted"

if not, you don't have a chance of getting the last row inserted.

to add to the above

phil, September 29, 2003 - 10:13 am UTC

...when I say get the last row inserted I mean the last row inserted for each account with the max balance date/time for each account

thanks

Tom Kyte
September 29, 2003 - 12:42 pm UTC



select *
from ( select account, balance, balance_date, max(balance_date) over
(partition by account) max_dt
from t )
where balance_date = max_dt;

does that. max_dt is set to the max_dt for each account.

you keep the row with the max_dt for each account.

would this do regarding above

phil, September 29, 2003 - 12:19 pm UTC

if pk is a sequence number ( i am only inserting to the accountbalance table ) ....

select * from (
select b.*,
max(pk) over (partition by account_fk) max_pk
from (
select pk,account_fk,balance_date_time,booked_balance,available_balance,
max(balance_date_time) over (partition by account_fk) max_date
from accountbalance
where account_fk in ( 1,2,3,4 )
) b
where balance_date_time = max_date
) where pk = max_pk

OK

Ram, May 14, 2004 - 8:35 am UTC

Dear Tom,
Do duplicate rows have different rowids?
Please see below.

SQL> show rel
release 902000100

SQL> select rowid,t.* from t t;

ROWID                       X                                                   
------------------ ----------                                                   
AAAHoZAABAAAMViAAD          1                                                   
AAAHoZAABAAAMViAAE          1                                                   
AAAHoZAABAAAMViAAF          1                                                   

Please do reply.
Bye!

 

Tom Kyte
May 14, 2004 - 10:24 am UTC

yes, each row in a table has a unique rowid. that is what rowid is all about.

doubts

A reader, May 14, 2004 - 10:27 pm UTC

Can you help me to know the solutions for the following
questions
1) There are 100 datafiles, numbered from 1 to 100. File number 10 is deleted and it has 500 MB of data. The database is working in No- Archive log mode. How can the database be recovered?

2) Same scenario as above with database working in archive-log mode. How can be the database recovered ? While doing recovery the archive logs aplied are from nos 1 to 100, but 50 gets crrupted. What do we do ? Can we proceed further ? If so how ?

3) A user has connect and resource privs allocated by the DBA . He is been allocated quota on three tablespaces by the DBA

- Default Tablespace Quota 500 M
- Tablespace 1 Quota 100 M
- Tablespace 2 Quota 200 M

Now the user tries to make a table which uses 300 M in tablespace 2. Will he be successful ?

4) There are about a 10,000 records in a table. A user 1 runs a query which is doing a full table scan. While doing the full table scan , user 2 changes some value x to y using a dml statement in record. What does the the 1-st user see ( x or y ) ? If x, then where is the value stored ?

Tom Kyte
May 15, 2004 - 12:37 pm UTC

1) there is insufficient data to answer.

the only answers I can give is either

a) the tablespace that contained file 10 is toast. gone. Hope it wasn't system.
b) you restore your last full backup and lose all work performed since

a and b are the reasons that running a production system in noarchive log mode is "not a good idea" (tm).

reminds me of a public service commercial about drug abuse. They would show a nice egg and say "this is your brain" (this is your database). They would then break the egg into a sizzling hot skillet and fry it -- "this is your brain on drugs" (this is your database in noarchivelog mode)...


2) take last hot backup of file 10, plop it down, recover it. if your archives are bad -- see #1.

3) think about it?

4) you *need* to read the concepts guide -- you must. really, it is mandatory. If you read it and retain 10% of it, you'll know 90% more than most people out there about Oracle.

This is the chapter on multi-versioning and read consistency. the most important features of the Oracle database.

Are rowids unique across partitioned tables ?

Valar, September 17, 2004 - 12:40 pm UTC

Hi Tom,

From the discussion above, I think it's good to assume that rowids are unique across partitioned tables also. I have a table namely template which is range partitioned on a field bio1id. Each partition is set to hold approximately 1 million records.

We were having a discussion on parallelizing a retrieval operation and a colleague of mine was suggesting that usage of rowid is better than the primary partitioned key.

Which of the two is better ?
Query Set 1:
select bio1id, egmtemplate, binmap
from template where bio1id between 1 and 3999999

select bio1id, egmtemplate, binmap
from template where bio1id between 4000000 and 7999999

...
Query Set 2:
select bio1id, egmtemplate, binmap
from template where rowid between 'AAALp6AARAAAAAJAAA'
and 'AAALp6AAuAAAA+ICcQ'

I was thinking that partition pruning would be in effect for the first query which would give the same performance as the queries with rowid. Please let us know.

Thanks,
Valar


Tom Kyte
September 17, 2004 - 1:25 pm UTC

if you want to parallelize at the partition level, why not use "from template partition(x)"?

rowids are unique within a table -- select * from t where rowid = :x will return at most a single record.


if you are trying to parallelize within a partition, you would want to use rowid ranges.

the "where column between A and B" will either

a) full scan the partition -- meaning both processes would read the ENTIRE partition

b) use an index to slowly read the partition slow by slow (hopefully this would not happen)


the rowid ranges let each process just read as much as it needs to read and stop -- they won't overlap, they wont contend with eachother.


see
</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:10498431232211 <code>
for a script that you can use to break a segment up, you might need to tweak for a partition.

Thanks !!

Valar, September 17, 2004 - 4:24 pm UTC

Thanks for the suggestions and the excellent pointer to the split script. I had to add an additional condition as  ' and data_object_id is not null' to the last inline select statement in the split script as follows.

(select data_object_id from user_objects where object_name  = upper('&TNAME')  and data_object_id is not null
)

Without the additional predicate clause, I was running into the following error.
SQL> @split
Enter value for chunks: 4
Enter value for tname: TEMPLATE
Enter value for user: FACEXPDBO
Enter value for tname: TEMPLATE
       GRP MIN_RID            MAX_RID
---------- ------------------ ------------------
         0 AAALp6AARAAAAAJAAA AAALp6AAuAAAA+ICcQ
         0 AAALqEAARAAAAAJAAA AAALqEAAuAAAA+ICcQ
         0 AAALvEAARAAAAAJAAA AAALvEAAuAAAA+ICcQ
         0 AAALvJAARAAAAAJAAA AAALvJAAuAAAA+ICcQ
         0 AAALvOAARAAAAAJAAA AAALvOAAuAAAA+ICcQ
         0 AAALw9AARAAAAAJAAA AAALw9AAuAAAA+ICcQ
         0 AAALxCAARAAAAAJAAA AAALxCAAuAAAA+ICcQ
         0 AAALxHAARAAAAAJAAA AAALxHAAuAAAA+ICcQ
         0 AAALxMAARAAAAAJAAA AAALxMAAuAAAA+ICcQ
         0 AAALxRAARAAAAAJAAA AAALxRAAuAAAA+ICcQ
         0 AAAL5rAARAAAAAJAAA AAAL5rAAuAAAA+ICcQ
         0 AAAL5wAARAAAAAJAAA AAAL5wAAuAAAA+ICcQ
         0 AAAL52AARAAAAAJAAA AAAL52AAuAAAA+ICcQ
         0 AAAL57AARAAAAAJAAA AAAL57AAuAAAA+ICcQ
         0 AAAL9jAARAAAAAJAAA AAAL9jAAuAAAA+ICcQ
ERROR:
ORA-01410: invalid ROWID
ORA-06512: at "SYS.DBMS_ROWID", line 38



15 rows selected.

Once I added the predicate clause, it worked fine and was returning 64 rows for the 16 partitions. I also did a count after doing a union query on the select rowids ranges to make sure the script alteration was okay. It matched up fine with the total count from the template table. 

Thanks again !!
Valar 

SQl Query

devenderkumar, May 20, 2011 - 11:34 pm UTC

Name

A
B
C
D

Output

D
B
C
A

an interview question I tell by taking alternative rows(even
and odd) merge with union in desc order but result is not getting.
Please help me.
Tom Kyte
May 23, 2011 - 11:46 am UTC

This is a silly interview question. It is really a "not smart" question, all it shows is the person that can code it knows some tricks. It is not really a good judge of overall capability at all.




ops$tkyte%ORA11GR2> with data as
  2  (select 'a' txt from dual union all
  3   select 'b' txt from dual union all
  4   select 'c' txt from dual union all
  5   select 'd' txt from dual
  6  )
  7  select txt, row_number() over (order by txt) rn
  8    from data
  9   order by mod(rn,2), txt DESC
 10  /

T         RN
- ----------
d          4
b          2
c          3
a          1