Oracle alter index/rebuild - oracle

If I rebuild an unusable index using alter index x rebuild, will the execution plan for any SQL that used that index previously be re-evaluated?
I know that the statistics are re-calculated as part of the rebuild in the DB version I'm using - Oracle 10.2.0.4.0.
I don't want to use the dbms_stats package to force the issue on this, seeing as I've already got fresh stats!

since the index is currently unusable, no SQL query uses the index. When you collect statistics (either through a rebuild or the dbms_stats package), all statements against the base table will be reparsed (hard-parse) next time they are submitted. Plans may change due to the stats update.
Rebuilding an unusable index will therefore make it visible and usable by all statements, even those that have been previously parsed.

Related

asynchronous global index maintenance for drop and truncate partition

We have a very large partitioned table that needs to drop partition periodically. The business system needs 7*24 hours of operation.
We use global index.
From the following article, we know that Oracle supports asynchronous index update.
https://oracle-base.com/articles/12c/asynchronous-global-index-maintenance-for-drop-and-truncate-partition-12cr1
But : "The actual index maintenance is performed at a later time"\
Does it affect the normal business when it is actually executed.( Query/Insert/Update/Delete )
No it doesn't, as you can read here (I supposed you are running 12.1 as you didn't specify database version and you linked 12.1 documentation).
The parts that are of interest to you are the following:
The partitions of tables containing local indexes are locked to prevent DML operations against the affect table partitions, except for an ONLINE MOVE operation. However, unlike the index maintenance for local indexes, any global index is still fully available for DML operations and does not affect the online availability of the OLTP system.
[...]
For example, dropping an old partition is semantically equivalent to deleting all the records of the old partition using the SQL DELETE statement. In the DML case, all index entries of the deleted data set have to be removed from any global index as a standard index maintenance operation, which does not affect the availability of an index for SELECT and DML operations.

How DBMS_STATS.GATHER_TABLE_STATS works in oracle

I need clarification on how DBMS_STATS.GATHER_TABLE_STATS works.
I have a scenario,were i am creating table and the same table is used in the package creation also.In other words the package compilation is depended on table creation.
Is it mandatory to include DBMS_STATS.GATHER_TABLE_STATS after index creation command in table creation script.
In which situation DBMS_STATS.GATHER_TABLE_STATS works,whether it's for package compilation or package execution.Please confirm.
DBMS_STATS provides information to the Oracle optimizer, enabling Oracle to build efficient execution plans for SQL statements. Optimizer statistics are never necessary for compiling objects.
Gathering statistics is such a complicated subject it can be difficult to even ask the right questions at first. I'd recommend starting by reading the manual, such as Managing Optimizer Statistics: Basic Topics.
Typically your statistics gathering strategy should look something like this:
Gather statistics manually whenever an object's data significantly changes.
Use the default autotask to automatically gather statistics for objects that have been slowly changing or were accidentally forgotten.
To answer some specific questions, you probably do not want to gather statistics right after creating a table. Only gather statistics after changing the data. Gathering statistics on an empty table can be dangerous; Oracle will think the table has 0 rows until the next time statistics are gathered. It would be better to have no statistics at all, then Oracle can use dynamic sampling to estimate the statistics.
(But on the other hand, if the table is created as a SELECT statement and contains a lot of data you may want to gather statistics. Then again, if you're using 12c it might gather statistics automatically when creating a table.)
You also generally do not need to gather statistics after creating an index. Oracle automatically gathers index statistics when an index is created or rebuilt.

Oracle 11g - Update bulk with index vs without

I have a table containing 50M records and I have to update almost all of it. I want to use parallel update on the table. Which will be faster, having indexes on the table or without?
If you're going to update almost all of the table, then I suspect the access method used will be a full table scan - which means the indexes won't be used to speed up the queries.
Therefore, the only impact that indexes may have will be the extra work required to maintain them for the update - so the more indexes, the slower your update will be.

Drop Empty Partition. Are indexes marked as invalid?

I want to drop a partition that is empty but I am aware about oracle setting all indexes to unusable whenever you perform a partition DDL statement like DROP, therefore, I should add UPDATE GLOBAL INDEXES to the statement though it looks unnecessary.
Then I came up with this post where it says that it wont mark it as unusable so I decided to test it. The thing is that I tested it in two oracle versions and it worked different!
Having two instances:
DBa(Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production)
DBb(Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production)
In DBa it marked them as invalid and in DBb which contained the same data than the other db (cloned with exp/imp) it succeed to drop without marking them unusable.
Is it possible to explicitly tell Oracle that you want to keep the indexes usable because there is no data in the partition (without rebuilding the indexes) ?
So far I am not able to find out why it was marked as invalid in a placed but not in the other one but there is something to say in case someone have the same problem.
Run it always with UPDATE GLOBAL INDEXES since if the partition is empty it will take no time to perform the drop and it ensures that the indexes will not be marked as invalid. Therefore, there is no reason to hope that oracle won't mark them
May be you can try below, this maintains index validity during the drop.
ALTER TABLE t1 DROP PARTITION p5 UPDATE GLOBAL INDEXES;
yes .. use LOCAL indexes while creating indexes over partitioned table

How to invalidate a SQL statement in the Oracle SQL area so that a new plan is produced when collecting statistics

I have a table and a query (within a PL/SQL packge) accessing that table. Statistics are collected weekly normally.
A large update has been run on the table, resulting in significantly different data distribution on a particular indexed column. The query plan used by Oracle (which I can see from v$sqlarea) is sub-optimal. If I take an explain plan on the same* query from SQL*Plus, a good plan is returned.
I have since collected statistics on the table. Oracle is still using the query plan that it originally came up with. v$sqlarea.last_load_time suggests this was a plan generated prior to the statistics generation. I thought regenerating statistics would have invalidated plans in the SQL cache.
Is there any way to remove just this statement from the SQL cache?
(* Not character-for-character, matches-in-the-SQL-cache same, but the same statement).
If you are using 10.2.0.4 or later, you should be able to use the DBMS_SHARED_POOL package to purge a single cursor from the shared pool.
I found out (when researching something else) that what I should have done was to use
no_invalidate => FALSE
When collecting the statistics by calling gather_table_stats. This would have caused all SQL plans referencing the table to immediately be invalidated.
The Oracle docs say:
Does not invalidate the dependent cursors if set to TRUE. The procedure
invalidates the dependent cursors immediately if set to FALSE. Use
DBMS_STATS.AUTO_INVALIDATE. to have Oracle decide when to invalidate dependent
cursors. This is the default.
The default of AUTO_INVALIDATE seems to cause invalidation of SQL statements within the next 5 hours. This is to stop massive number of hard-parses if you are collecting statistics on lots of objects.

Resources