Excellent
pawan, March 12, 2002 - 7:16 pm UTC
I think Tom has gone over this atleast 10 times and I totally agree with him. I used to awake at 2 AM reorganizing Indexes and never kept any metrices so am not sure whether it helped. My question though is if there exists with Tom a script/method to gather statistics on a regular basis ( before and after).
Thanks
March 13, 2002 - 6:57 am UTC
things like statspack (IO's and waits), application logs (showing transactions processed, response times), tkprof reports are what you need.
LMT
Dusan Valasek, March 13, 2002 - 1:36 am UTC
"How
to stop defragmenting and start living: the definitive world of fragmentation" - there is the only answer: Start living in Locally Managed Tablespaces.
Index fragmented in LMT
KJ, March 05, 2004 - 6:45 am UTC
Hi Tom
This is a DW database - 9.2.0.4
analyze index NON_TRADE_ACCOUNT_BALANCE_PK validate structure;
select trunc(100*(del_lf_rows/lf_rows)) pct_deleted, pct_used from index_stats - gave a 47%
It is a LMT - Automatic Allocation and Auto Segment Space management. Should we check for fragmentation even with LMT's? I see few other indexes with the same issue too.
Thanks
March 05, 2004 - 8:37 am UTC
that is not fragmented.
that might be very very very very normal for that index.
rebuilding it might just result in increased redo
or
rebuilding it might result in reduced LIO's during the day
All this means is you apply inserts, updates and deletes against this index.
Try alter index iname coalesce; that might be all you need (an online operation).
Index fragmented in LMT
KJ, March 05, 2004 - 7:02 am UTC
Hi Tom
This is a DW database - 9.2.0.4
analyze index NON_TRADE_ACCOUNT_BALANCE_PK validate structure;
select trunc(100*(del_lf_rows/lf_rows)) pct_deleted, pct_used from index_stats - gave a 47%
It is a LMT - Automatic Allocation and Auto Segment Space management. Should we check for fragmentation even with LMT's? I see few other indexes with the same issue too.
Thanks
height is 4
READER, May 17, 2004 - 8:53 pm UTC
validate index xxx
select * from index_stats reveals that the height is 4 .
What does this mean ?
root,branch,leaf ...
Is it bad ?
Thanks
May 18, 2004 - 11:14 am UTC
root -> branch -> branch -> leaf
means it'll take 4lio's to get from a key value to a leaf node.
is it bad? insufficient data to comment. size of key? number of distinct vlaues of key? block size? ....
OEM Reorganization Features
reader, May 18, 2004 - 11:38 am UTC
With 9.2 OEM allows for online reorganization of tables
and indexes that include function-based and reverse-key
indexes. You can validate the structure of an object while
users are making changes to a table.
It will generate an Impact and Job Summary Report.
Haven't made use of this feature myself so can't offer any concrete evidence of it's usefulness and performance.
May 18, 2004 - 6:16 pm UTC
well, the database has allowed for online stuff for a while, doesn't need a gui or anything.
but -- just because you see the number "4" doesn't mean *anything*
Height=4
Reader, May 18, 2004 - 7:52 pm UTC
select height,blocks,lf_rows,lf_blks,br_rows,distinct_keys from index_stats
HEIGHT BLOCKS LF_ROWS LF_BLKS BR_ROWS DISTINCT_KEYS
---------- ---------- ---------- ---------- ---------- -------------
4 158981 42478952 154898 154897 5666
Block size = 8k
Thanks
May 19, 2004 - 7:46 am UTC
hows about showing the entire index_stats view -- but with 42million entries, it doesn't seem unreasonable yet.
READER, May 19, 2004 - 9:05 pm UTC
PRE_ROWS_LEN HEIGHT BLOCKS LF_ROWS LF_BLKS LF_ROWS_LEN LF_BLK_LEN BR_ROWS BR_BLKS BR_ROWS_LEN BR_BLK_LEN DEL_LF_ROWS DEL_LF_ROWS_LEN DISTINCT_KEYS MOST_REPEATED_KEY BTREE_SPACE USED_SPACE PCT_USED ROWS_PER_KEY BLKS_GETS_PER_ACCESS PRE_ROWS
0 4 158981 42478952 154898 1061973800 7996 154897 847 4117920 8028 0 0 5666 90747 1245364124 1066091720 86 7497.16766678433 3753.08383339216 0
Thanks
May 20, 2004 - 10:18 am UTC
you have no real "whitespace" (0 deleted leaf rows). You are 86% utilized (pretty packed).
It is what it is, the only real way to reduce the height would be to partition it into N smaller indexes.
but -- since each key retrieved 7k plus rows -- that really doesn't matter - so what if it takes 4lios to get to the leaf, if it is going to have to range scan for 7k rows after that. even reducing the height of the index by 1 or 2 would remove only 1 or 2 lios from the range scan (which on average is going to have 3753 LIOs anyway)
this looks fine.
Range Scan --LIO's
Reader, May 21, 2004 - 8:24 am UTC
Tom,
When it is doing a Range scan to find a particular Row Why will it do 3753 LIO's ?
Is it true that while doing a Range Scan Oracle reads only one block at a time.
Why can't it do multi-block reads at this point .
Thanks for clarifying .
May 21, 2004 - 10:57 am UTC
3753.08383339216
because the estimated block gets per access said it would.
indexes are stored in blocks, blocks all over the place. Leaf blocks are not stored "next to eachother" (cannot be). to get from leaf block 1 to leaf block 2 -- you have to do an IO of another block somewhere else.
Also, there is the table access by index rowid to be considered as well (each entry on the index could be pointing to a different block in the table itself).
indexes on LMT
Sudip Sarkar, August 15, 2007 - 11:37 am UTC
Hi Tom,
My DBA says "Now that all data is on a SAN, the need for separation of data and index is no longer required from a hardware perspective.
And, with locally managed tablespaces with automatic extent sizing and automatic segment space management, fragmentation is supposed to be a thing of the past. "
Is this true that we dont need to create a separate tablespaces for Indexes anymore?
Thanks and Regards
August 20, 2007 - 7:18 pm UTC
SAN - spam - nam - ugh
SAN has nothing to do with it
NAS has nothing to do with it
It was never true, never, that table data and index data needed to be separate. It was always a myth.
It had nothing to do with fragmentation either.
It has nothing to do with extents and how they are allocated.
It never did.
You always and forever should have used tablespaces to make YOUR LIFE EASIER, BETTER, MORE HAPPY.
Do whatever is right for you.
Use tablespaces to administer, book keep, organize. that is all.
Fragmented Index
A reader, April 02, 2009 - 1:41 am UTC
Hi Tom
We have a large table of about 100 millions records. It was determined that the ninety percent of the records of the table were not useful. The tables has a unique sid as its primary key/unique key. Now when I delete the table and its depended table the keys would like the below. There are large gaps in the unique key.
Before
Unique Key
1
2
3
4
.
.
After
Unique Key
1
7
19
35
.
.
Before Delete Statistics
INDEX_NAME INDEX_TYPE TABLE_OWNER TABLE_NAME TABLE_TYPE UNIQUENESS COMPRESSION PREFIX_LENGTH TABLESPACE_NAME INI_TRANS MAX_TRANS INITIAL_EXTENT NEXT_EXTENT MIN_EXTENTS MAX_EXTENTS PCT_INCREASE PCT_THRESHOLD INCLUDE_COLUMN FREELISTS FREELIST_GROUPS PCT_FREE LOGGING BLEVEL LEAF_BLOCKS DISTINCT_KEYS AVG_LEAF_BLOCKS_PER_KEY AVG_DATA_BLOCKS_PER_KEY CLUSTERING_FACTOR STATUS NUM_ROWS SAMPLE_SIZE LAST_ANALYZED DEGREE INSTANCES PARTITIONED TEMPORARY GENERATED SECONDARY BUFFER_POOL USER_STATS DURATION PCT_DIRECT_ACCESS ITYP_OWNER ITYP_NAME PARAMETERS GLOBAL_STATS DOMIDX_STATUS DOMIDX_OPSTATUS FUNCIDX_STATUS JOIN_INDEX
ACC_CUST_START_END NORMAL COS ACC TABLE NONUNIQUE DISABLED USERS_IDX 2 255 134217728 1048576 1 2147483645 0 0 NO 3 506265 460494 1 58 26812095 VALID 97659470 19531894 3/28/2009 2:41 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX1 NORMAL COS ACC TABLE NONUNIQUE DISABLED USERS_IDX 2 255 268435456 1048576 1 2147483645 0 0 NO 3 565090 16077089 1 3 60398500 VALID 97321855 19464371 3/28/2009 2:44 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX2 NORMAL COS ACC TABLE NONUNIQUE DISABLED USERS_IDX 2 255 268435456 1048576 1 2147483645 0 0 NO 3 538750 7240761 1 12 87569530 VALID 97224330 19444866 3/28/2009 2:46 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX3 NORMAL COS ACC TABLE UNIQUE DISABLED USERS_IDX 2 255 67108864 1048576 1 2147483645 0 0 NO 2 199720 97169825 1 1 1586450 VALID 97169825 19433965 3/28/2009 2:40 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX4 NORMAL COS ACC TABLE NONUNIQUE DISABLED USERS_IDX 2 255 134217728 1048576 1 2147483645 0 10 NO 3 443750 13348 33 112 1496360 VALID 97432125 19486425 3/28/2009 2:48 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX5 NORMAL COS ACC TABLE NONUNIQUE DISABLED P_IDX 2 255 20971520 2097152 1 2147483645 0 10 NO 3 222000 6208 35 172 1072645 VALID 77145765 15429153 3/28/2009 2:49 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX6 NORMAL COS ACC TABLE NONUNIQUE DISABLED USERS_IDX 2 255 67108864 1048576 1 2147483645 0 0 NO 3 268480 11345 23 124 1415675 VALID 97274285 19454857 3/28/2009 2:49 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX1 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED P_IDX 2 255 67108864 2097152 1 2147483645 0 0 NO 2 142045 57942560 1 1 4678395 VALID 58706975 11741395 3/28/2009 4:47 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX2 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED USERS_IDX 2 255 33554432 1048576 1 2147483645 0 10 NO 2 50370 16819865 1 1 557860 VALID 16819905 3363981 3/28/2009 4:45 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX3 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED USERS_IDX 2 255 1048576 1048576 1 2147483645 0 10 NO 0 1 102 1 1 72 VALID 103 103 3/28/2009 4:45 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX4 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED USERS_IDX 2 255 16384 1048576 1 2147483645 0 10 NO 0 1 33 1 1 32 VALID 33 33 3/28/2009 4:45 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX5 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED USERS_IDX 2 255 1048576 1048576 1 2147483645 0 40 NO 2 585 144929 1 1 6809 VALID 144948 144948 3/28/2009 4:45 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX6 NORMAL COS ITEMS TABLE UNIQUE DISABLED USERS_IDX 2 255 134217728 1048576 1 2147483645 0 0 NO 3 279335 76396450 1 1 1805805 VALID 76396450 15279290 3/28/2009 4:43 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX7 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED P_IDX 2 255 20971520 2097152 1 2147483645 0 10 NO 3 236505 171166 1 4 845735 VALID 76257745 15251549 3/28/2009 4:48 1 1 NO N N N DEFAULT NO YES NO
After Delete Statistics
INDEX_NAME INDEX_TYPE TABLE_OWNER TABLE_NAME TABLE_TYPE UNIQUENESS COMPRESSION PREFIX_LENGTH TABLESPACE_NAME INI_TRANS MAX_TRANS INITIAL_EXTENT NEXT_EXTENT MIN_EXTENTS MAX_EXTENTS PCT_INCREASE PCT_THRESHOLD INCLUDE_COLUMN FREELISTS FREELIST_GROUPS PCT_FREE LOGGING BLEVEL LEAF_BLOCKS DISTINCT_KEYS AVG_LEAF_BLOCKS_PER_KEY AVG_DATA_BLOCKS_PER_KEY CLUSTERING_FACTOR STATUS NUM_ROWS SAMPLE_SIZE LAST_ANALYZED DEGREE INSTANCES PARTITIONED TEMPORARY GENERATED SECONDARY BUFFER_POOL USER_STATS DURATION PCT_DIRECT_ACCESS ITYP_OWNER ITYP_NAME PARAMETERS GLOBAL_STATS DOMIDX_STATUS DOMIDX_OPSTATUS FUNCIDX_STATUS JOIN_INDEX
ACC_CUST_START_END NORMAL COS ACC TABLE NONUNIQUE DISABLED P_IDX 2 255 2097152 2097152 1 2147483645 0 10 NO 3 74980 254243 1 37 9579550 VALID 16273950 3254790 3/25/2009 16:37 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX1 NORMAL COS ACC TABLE NONUNIQUE DISABLED P_IDX 2 255 2097152 2097152 1 2147483645 0 10 NO 2 74750 1689094 1 7 12703050 VALID 16237870 3247574 3/25/2009 16:36 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX2 NORMAL COS ACC TABLE NONUNIQUE DISABLED P_IDX 2 255 2097152 2097152 1 2147483645 0 10 NO 3 77200 705438 1 21 14876310 VALID 16293015 3258603 3/25/2009 16:37 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX3 NORMAL COS ACC TABLE UNIQUE DISABLED P_IDX 2 255 2097152 2097152 1 2147483645 0 10 NO 2 37205 16481695 1 1 1114500 VALID 16481695 3296339 3/25/2009 16:37 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX4 NORMAL COS ACC TABLE NONUNIQUE DISABLED P_IDX 2 255 2097152 2097152 1 2147483645 0 10 NO 2 57040 9367 6 41 385830 VALID 16370660 3274132 3/25/2009 16:37 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX5 NORMAL COS ACC TABLE NONUNIQUE DISABLED P_IDX 2 255 2097152 2097152 1 2147483645 0 10 NO 2 23925 3498 6 61 214405 VALID 10723425 2144685 3/25/2009 16:37 1 1 NO N N N DEFAULT NO YES NO
ACC_IDX6 NORMAL COS ACC TABLE NONUNIQUE DISABLED P_IDX 2 255 2097152 2097152 1 2147483645 0 10 NO 2 37040 7774 4 62 485965 VALID 16618285 3323657 3/25/2009 16:37 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX1 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED P_IDX 2 255 67108864 2097152 1 2147483645 0 0 NO 2 131430 14005580 1 1 2123965 VALID 14291660 2858332 3/25/2009 16:41 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX2 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED USERS_IDX 2 255 33554432 1048576 1 2147483645 0 10 NO 2 50345 16853370 1 1 559325 VALID 16853370 3370674 3/25/2009 16:40 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX3 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED USERS_IDX 2 255 1048576 1048576 1 2147483645 0 10 NO 0 1 102 1 1 72 VALID 103 103 3/25/2009 16:40 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX4 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED USERS_IDX 2 255 16384 1048576 1 2147483645 0 10 NO 0 1 33 1 1 32 VALID 33 33 3/25/2009 16:40 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX5 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED USERS_IDX 2 255 1048576 1048576 1 2147483645 0 40 NO 2 585 144929 1 1 6809 VALID 144948 144948 3/25/2009 16:40 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX6 NORMAL COS ITEMS TABLE UNIQUE DISABLED USERS_IDX 2 255 134217728 1048576 1 2147483645 0 0 NO 3 254560 31011190 1 1 1091925 VALID 31011190 6202238 3/25/2009 16:40 1 1 NO N N N DEFAULT NO YES NO
MTRI_IDX7 NORMAL COS ITEMS TABLE NONUNIQUE DISABLED P_IDX 2 255 20971520 2097152 1 2147483645 0 10 NO 3 207535 165018 1 4 700995 VALID 31252925 6250585 3/25/2009 16:42 1 1 NO N N N DEFAULT NO YES NO
I am seeing a performance degradation after the delete.
Thanks a lot for the valuable help to the community.
How do I improve the performance?
April 02, 2009 - 9:45 am UTC
you do understand that no one could make any sort of comment regarding this right?
so what if there are gaps. big deal.
I see a ton of information (wholly unreadable, but lots of it)
And then a "it runs slow"
with no information about what "it" is, what "it" does, how fast "it" used to be, how slow "it" is now, what you have done yourself to research "it" and so on...
A reader, April 02, 2009 - 2:30 pm UTC
Sorry about the above email. I didnt know what columns were relevant to answer the question.
I have started rerunning the processes to gather the trace files to know where the access paths have changed.
Index rebuild,fragmentation
Bhaskar, April 30, 2012 - 7:08 am UTC
Hi Tom,
I have read your book as well as all your posts regarding index rebuild.
From all of them now i'm confirmed the index rebuild is not a permanent solutio n of a slow running query or well mannerd index.
Now i have below questions
1. What actually happens when we rebuild an index?Does we re-create an index from the old one?
2. Then new one would be the same as old one only extra time we spent and some unnecessary redo,undo got generated.
3. Also in OS we usually have fragmentation so does the same thing happen to index also? I mean if we do massive deletion every day on differnt data condition is there any chance massive de fragmentation will happen?
I think i'm stating something wrong in point 3 but i have no clear idea how massive deletion in every day will cause fragmentation in index.
4. As we know index is a balanced tree will index rebuild can cause index depth reduction ? I know in index copression sometimes it may do.
can please help me in clearing all these concepts.
Thanks in advance.
April 30, 2012 - 8:42 am UTC
1) in general - an index rebuild will read the old index IF POSSIBLE (not always possible) and write a new, compact structure from that.
if the index was set unusable and more data was loaded - that won't be possible and the index rebuild will read the existing table - sort the data and build a new index from that.
2) well, it would not be unnecessary - it would be necessary redo. But you would also have the extra IO that took place, you would have the extra CPU that was used, you would have the increased query response times during the rebuild due to this, you would have (pre-11g) a lock taken before and right at the end of the rebuild contending with your users.
3) huh? I don't know what you mean. If you are talking about 'disk fragmentation' that you would run a disk defragger on - it has no bearing or relevance to storage management within an index.
If you find yourself doing massive deletions every day - please try to think of a way NOT to do that. Delete is the single most expensive DML you can do (well, short of an update that moves a row - like a partition key update - that is a delete+insert)
Look into partitioning for example and use truncate or drop
4) a rebuild could cause a temporary reduction in the height of an index, yes.
index rebuild,fragmentation
Bhaskar, April 30, 2012 - 7:12 am UTC
Sorry in point 3 it should be fragmentation.
index rebuild,fragmentation
Bhaskar, May 02, 2012 - 12:51 am UTC
Hi Tom,
Thanks for the information.
"1) in general - an index rebuild will read the old index IF POSSIBLE (not always possible) and write a new, compact structure from that. "
As mentioned below for point 1 only if index is in unusable state then index rebuild will read the data from table and in in all othere cases ir will read teh old index for rebuild.
Also as you mentioned it will compact the structure - does it mean it will remove holes craeted in the index?
Also can you please explain how it will compact the structure?
"3) huh? I don't know what you mean.."
Actually i was thinking if we delete some entries from an index the space owned by those entires will no longer be used so there will be hole.
I know if an index is created on a sequenced column and we delete some sequences the space owned by those deleted sequences will create a hole because
we will not be able to regain those spaces.Is it correct?
So will rebuild be in the perfect choice for this above scenarion?
Also say we have an index in name column which contains data like "ram","shyam","nick".Now if we delete "shyam" the space owned by "shyam" entry how will
be used again if we put a new value "john" after deleting "shyam".
Thanks in advance.
May 02, 2012 - 1:28 pm UTC
1) if the index is valid and usable - a rebuild will read the existing index to create a new one.
It writes out a perfectly compact - filled to pctfree - set of blocks. There will be not extraneous space.
3) you just described what I call a "sweeper" index.
search this site for "sweeper"
a coalesce might be a better option than a rebuild.
For data that is monotonically increasing/decreasing (sequences, dates, timestamps for example) - where you delete a lot but NOT ALL of the old data - you may end up with an index where the left hand side is very sparsely populated but the right hand side is very dense. these indexes may need to be coalesced or rebuilt from time to time in order to correct this.
For data that arrives randomly - like NAME - you typically do not need to perform this operation since the entire breadth of the index is constantly being used.
index rebuild,fragmentation
Bhaskar, May 02, 2012 - 1:26 am UTC
In addition to above for point 3 i have read in a documentation that deleted space will not be automatically reclaimed if an exact match key is inserted.
In my scenarion if we delete "shyam" and do not put values "shyam" and put new value "john" then index on ename column will have a blank space created
by "shyam".
So if we rebuild the index then this deleted space will be reclaimed. Is it right Tom?
Thanks in advance.
May 02, 2012 - 1:29 pm UTC
that is not true at all.
we can reuse "shyam" to store "john"
Bhaskar, May 08, 2012 - 6:56 am UTC
Thnaks Tom.
Index deleted space reuse
Bhaskar, May 09, 2012 - 6:36 am UTC
Hi Tom,
Thanks for all the suggestions.
Still i have one doubt perhaps it's my wrong concept but can you please help me in understanding the below issue.
"we can reuse "shyam" to store "john" "
So in this case in if we delete row with value "John" data block which was storing the value "John" will be empty.
The word "Shyam" comes after "John" by binary value.
Then If we don't insert "John" but "Shyam" how that particular block which was previously containing value "John" will now have the value "Shyam"
Thanks in advance.
May 10, 2012 - 3:16 am UTC
let's say the index leaf block was:
Isabel, John, Larry, Paul, Sally, Tom
And that block was 'full'
You delete John, there is now more room on it. So, you go to insert Shyam. Shyam has to go in between Sally and Tom.
There is room on the leaf block for that now, we'll put Shyam right in between the two.
Bhaskar, May 10, 2012 - 4:28 am UTC
Hi Tom,
Thanks.
Then you are shyam will be put in the deleted space of john?
May 10, 2012 - 8:54 am UTC
not necessarily in the same exact place - we might move the bytes around on the block. But that space *can* and *will* be reused.
Bhaskar, May 11, 2012 - 12:55 am UTC
Thanks Tom.
Doubt
A reader, August 31, 2012 - 12:10 pm UTC
so without reorg you are saying that oracle will reuse the space.
in that case why do we need to deal high water mark of a block
Please advise
September 10, 2012 - 6:46 pm UTC
I never said that, please point to where I said that.
the space *will be reused*.
you said it
A reader, December 15, 2012 - 8:20 am UTC
Here you said it..
Followup May 10, 2012 - 8am Central time zone:
not necessarily in the same exact place - we might move the bytes around on the block. But that space *can* and *will* be reused.
December 18, 2012 - 7:44 am UTC
sorry, I misread you, i thought you meant the space would not be reused - that should have been obvious from me emphatically stating that the space would be reused.
You worry about high water marks sometimes if you are
a) doing full scans, we always scan to the high water mark.
b) just finished a purge of data that dramatically reduced the space needed by this segment and you could reuse that space elsewhere
c) do a ton of indexed reads into this table with lots of free space - you'll be able to cache the table blocks better in the cache if they were more 'dense'
index stats
A Reader, January 02, 2013 - 2:33 am UTC
Tom,
Table t11 and indexes on table t11 are detailed below.
SQL> desc t11;
Name Null? Type
------------------------------------------------------------------- -------- ---------------------------------------------
PARAMETERINSTANCEID NUMBER
PARAMINSTANCE2PARAMSETVERSION NUMBER
PARAMINSTANCE2PARAMDEFINITION NUMBER
PARAMINSTANCE2PARENTPARAM NUMBER
SEQUENCE NUMBER
X_CTCV_CONV_ID VARCHAR2(50 CHAR)
X_CONV_RUN_NO NUMBER
SQL> select dic.index_name, dic.table_name, dic.column_name, dic.column_position, di.index_type from dba_ind_columns dic, dba_indexes di
2 where di.table_name ='t1' and DIC.index_NAME = di.index_name;
INDEX_NAME TABLE_NAME COLUMN_NAME COLUMN_POSITION INDEX_TYPE
--------------- ------------------------------ ------------------------------ --------------- ----------
PI_UK t11 PARAMINSTANCE2PARAMSETVERSION 1 NORMAL
PI_UK t11 PARAMINSTANCE2PARAMDEFINITION 2 NORMAL
PI_PK t11 PARAMETERINSTANCEID 1 NORMAL
PI_PAD_FK_I t11 PARAMINSTANCE2PARAMDEFINITION 1 NORMAL
PI_PI_FK_I t11 PARAMINSTANCE2PARENTPARAM 1 NORMAL
SQL> select sum(bytes/1024/1024/1024) size_gb from dba_segments where segment_name = 't11';
SIZE_GB
----------
371.40625
SQL> select sum(bytes/1024/1024/1024) size_gb from dba_segments where segment_name = 'PI_UK';
SIZE_GB
----------
411.938477
SQL> select sum(bytes/1024/1024/1024) size_gb from dba_segments where segment_name = 'PI_PK';
SIZE_GB
----------
243.816406
SQL> select sum(bytes/1024/1024/1024) size_gb from dba_segments where segment_name = 'PI_PAD_FK_I';
SIZE_GB
----------
470.986328
SQL> select sum(bytes/1024/1024/1024) size_gb from dba_segments where segment_name = 'PI_PI_FK_I';
SIZE_GB
----------
.010742188
we have 02 indexes here more than the table size...
table t11 is range partitioned.
since all table data is sitting in single partition so is the index partition.
INDEX_STATS for PI_UK is as follows.
SQL> exec print_table('select * from bde_index_stats where partition_name=''PI_P01''');
HEIGHT : 5
BLOCKS : 53992320
NAME : PI_UK
PARTITION_NAME : PI_P01
LF_ROWS : 1120039324
LF_BLKS : 53804613
LF_ROWS_LEN : 213287053602
LF_BLK_LEN : 7396
BR_ROWS : 53804612
BR_BLKS : 187204
BR_ROWS_LEN : 825251980
BR_BLK_LEN : 8028
DEL_LF_ROWS : 10727072
DEL_LF_ROWS_LEN : 235895058
DISTINCT_KEYS : 1120039324
MOST_REPEATED_KEY : 1
BTREE_SPACE : 399441791460
USED_SPACE : 214112305582
PCT_USED : 54
ROWS_PER_KEY : 1
BLKS_GETS_PER_ACCESS : 6
PRE_ROWS : 0
PRE_ROWS_LEN : 0
OPT_CMPR_COUNT : 0
OPT_CMPR_PCTSAVE : 0
Question/comments
a) By re-partitioning( at the moment table is range partitioned but all the data flowing into 1st partition.. range is so high ) the table would it help in reducing the index height it is 5 at the moment. Would reducing height by 1 or 2 would be really helpful?
b) PCT_USED value of index_stats is 54, - this signifies the index is not compact.. also there are over 10million DEL_LF_ROWS - so would you recommed coalsce or index rebuild in this case?
c) we have BTREE_SPACE around 400gb and USED_SPACE around 214gb .. again it points to index not compact !
regards
b)
January 04, 2013 - 2:00 pm UTC
a) depends - do you do range scans or mostly just single row fetches from this index.
a single row fetch would do ~32% less IO if you reduced the index from 5 to 3. It would do ~16% less IO if you reduced the index from 5 to 4.
if you fetch lots of rows - say 20, then reducing from 5 to 3 would reduce IOs by about ~8%, from 5 to 4 about ~4%. If you fetch 200 rows, then about 0.9% and 0.4%.
it depends on where you spend your IO's...
b) probably, this index is probably what I call a sweeper index (search this site for that phrase to read about that)
c) see (b)
..index stats
A Reader, January 04, 2013 - 4:16 pm UTC
Thanks Tom,
I will look for sweeper indexes which you refrred to .
next thing which is puzzling me is.
a) Index LF_rows count is 1/8 of the count(*) in the table.
index is on 02 column c1,c2 -- c1 being the partition key.
select count(*) from t -- 8 billion
select sum(lf_rows) from index_stats where index_name = 'that index' -- 1 billion + 11
select count(*) from t where c1 is NULL -- 11
select count(*) from t where c1 is null and c2 is null -- 0
why index rows and table rows are matching ( i have accounted for NULLs as above )
b) if table T has index t_idx on ( c1,c2 ) column of t
so size of index t_idx ( when no nulls on c1 and c2) > size of index t_idx ( when there are 80% nulls on c1 and c2) . this would be True? -- as nulls entried wount be keyed in index.
January 14, 2013 - 10:05 am UTC
a) because index stats only ever has but one row. It'll be for the last partition unless you tell us what partition to do.
ops$tkyte%ORA11GR2> CREATE TABLE t
2 (
3 dt date,
4 x int,
5 y varchar2(30)
6 )
7 PARTITION BY RANGE (dt)
8 -- subpartition by hash(x)
9 (
10 PARTITION part1 VALUES LESS THAN (to_date('13-mar-2003','dd-mon-yyyy')) ,
11 PARTITION part2 VALUES LESS THAN (to_date('14-mar-2003','dd-mon-yyyy')) ,
12 PARTITION junk VALUES LESS THAN (MAXVALUE)
13 )
14 /
Table created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> insert into t select to_date( '12-mar-2003','dd-mon-yyyy')+mod(rownum,3), user_id, username from all_users;
48 rows created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> create index t_idx on t(dt,x) local;
Index created.
ops$tkyte%ORA11GR2> analyze index t_idx validate structure;
Index analyzed.
ops$tkyte%ORA11GR2> select partition_name, lf_rows from index_stats;
PARTITION_NAME LF_ROWS
------------------------------ ----------
JUNK 16
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> analyze index t_idx partition(part1) validate structure;
Index analyzed.
ops$tkyte%ORA11GR2> select partition_name, lf_rows from index_stats;
PARTITION_NAME LF_ROWS
------------------------------ ----------
PART1 16
ops$tkyte%ORA11GR2> analyze index t_idx partition(part2) validate structure;
Index analyzed.
ops$tkyte%ORA11GR2> select partition_name, lf_rows from index_stats;
PARTITION_NAME LF_ROWS
------------------------------ ----------
PART2 16
ops$tkyte%ORA11GR2> analyze index t_idx partition(junk) validate structure;
Index analyzed.
ops$tkyte%ORA11GR2> select partition_name, lf_rows from index_stats;
PARTITION_NAME LF_ROWS
------------------------------ ----------
JUNK 16
you'd have to run it for each partition, save the results after each run and then add them up.
b) probably - not guaranteed - but probably... Since 80% of the rows would not be in the second index...
(but think about a case where it might not be true :) )
ops$tkyte%ORA11GR2> create table t1 ( x varchar2(80), y varchar2(80) );
Table created.
ops$tkyte%ORA11GR2> insert into t1 select <b><fill in the blanks!></b> from all_objects;
72998 rows created.
ops$tkyte%ORA11GR2> create index t1_idx on t1(x,y);
Index created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> create table t2 ( x varchar2(80), y varchar2(80) );
Table created.
ops$tkyte%ORA11GR2> insert into t2 select <b><fill in the blanks!></b> from all_objects;
73000 rows created.
ops$tkyte%ORA11GR2> create index t2_idx on t2(x,y);
Index created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> select count(x||y), count(*) from t1;
COUNT(X||Y) COUNT(*)
----------- ----------
72998 72998
ops$tkyte%ORA11GR2> select count(x||y), count(*) from t2;
COUNT(X||Y) COUNT(*)
----------- ----------
14600 73000
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> analyze index t1_idx validate structure;
Index analyzed.
ops$tkyte%ORA11GR2> select name, btree_space, used_space from index_stats;
NAME BTREE_SPACE USED_SPACE
------------------------------ ----------- ----------
T1_IDX 1231416 1097553
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> analyze index t2_idx validate structure;
Index analyzed.
ops$tkyte%ORA11GR2> select name, btree_space, used_space from index_stats;
NAME BTREE_SPACE USED_SPACE
------------------------------ ----------- ----------
T2_IDX 2926824 2588084
..index stats
A Reader, January 10, 2013 - 1:44 am UTC
Sorry Tom,
Just a typo above
the line
...why index rows and table rows are matching ( i have accounted for NULLs as above )
is corrected to
why index rows and table rows are *NOT* matching ( i have accounted for NULLs as above )
..Index Stats
A Reader, January 20, 2013 - 11:02 pm UTC
Sorry Tom
for not making the things clear in the begining.
when you said :
....a) because index stats only ever has but one row. It'll be for the last partition unless you tell us what partition to do.
we did calculated for each of the parition and stored those stats into a a table bde_index_stats.
The given output is for the 1st partition.
SQL> exec print_table('select * from bde_index_stats where partition_name=''PI_P01''');
HEIGHT : 5
BLOCKS : 53992320
NAME : PI_UK
PARTITION_NAME : PI_P01
LF_ROWS : 1120039324
LF_BLKS : 53804613
LF_ROWS_LEN : 213287053602
LF_BLK_LEN : 7396
BR_ROWS : 53804612
BR_BLKS : 187204
BR_ROWS_LEN : 825251980
BR_BLK_LEN : 8028
DEL_LF_ROWS : 10727072
DEL_LF_ROWS_LEN : 235895058
DISTINCT_KEYS : 1120039324
MOST_REPEATED_KEY : 1
BTREE_SPACE : 399441791460
USED_SPACE : 214112305582
PCT_USED : 54
ROWS_PER_KEY : 1
BLKS_GETS_PER_ACCESS : 6
PRE_ROWS : 0
PRE_ROWS_LEN : 0
OPT_CMPR_COUNT : 0
OPT_CMPR_PCTSAVE : 0
and other partitions have NO data ( except the maxva partition which has 11 rows) . so I have included that output above.
Here is the count partition_name, lf_rows from table bde_index_stats;
PARTITION_NAME LF_ROWS
PI_P01 1,120,039,324
PI_P02 0
PI_P03 0
PI_P04 0
PI_P05 0
PI_P06 0
PI_P07 0
PI_P08 0
PI_P09 0
PI_P10 0
PI_PMAXVALUE 11
So could you please suggest on the earlier question ..
as mentioned below
a) Index LF_rows count is 1/8 of the count(*) in the table.
index is on 02 column c1,c2 -- c1 being the partition key.
select count(*) from t -- 8 billion
select sum(lf_rows) from index_stats where index_name = 'that index' -- 1 billion + 11
regards
January 21, 2013 - 7:38 am UTC
show your work step by step by step.
this doesn't match up with what you said the first time, show all steps.
cut and paste.
11g differences in log function?
A reader, January 22, 2013 - 9:06 am UTC
Keeping in mind that reorgs are 99% a waste of time, I ran this out of curiousity and got the followingin 11.2.0.3:
SQL> @indexfrag
decode (sign(ceil(log(br_blk_len/(br_rows_len/br_rows),
*
ERROR at line 4:
ORA-00909: invalid number of arguments
January 23, 2013 - 1:00 am UTC
who ever posted their query originally had a cut and paste error in it - that query (which I never ran or tested) never worked.
log(br_blk_len/(br_rows_len/br_rows),
lf_blk_len/((lf_rows_len - del_lf_rows_len)/(lf_rows - del_lf_rows)
+1 - height), -1,'YES','NO')
is not a valid call to log, they lost some closing parens there.
A reader, March 14, 2025 - 11:33 am UTC
Hi Tom , your response is contradiction to the actual performance and benefits of index rebuilds post mass data purging as it can be viewed in practical critical systems.
March 14, 2025 - 1:41 pm UTC
While there can be benefit in these cases, how often do you do mass data purges?