Oracle Is it necessary to gather table stats for a new table with new index? - oracle

I just created a new table on 11gR2 and loaded it with data with no index. After the loading was completed, I created several indexes on the new table including primary constraint.
CREATE TABLE xxxx (col1 varchar2(20), ...., coln varhcar2(10));
INSERT INTO xxxx SELECT * FROM another_table;
ALTER TABLE xxxx ADD CONSTRAINT xxxc PRIMARY KEY(col_list);
CREATE INDEX xxxx_idx1 ON xxxx (col3,col4);
AT this point do I still need to use DBMS_STATS.GATHER_TABLE_STATS(v_owner,'XXXX') to gather table stats?
If yes, why? since Oracle says in docs "Oracle Database now automatically collects statistics during index creation and rebuild".
I don't want to wait for automatic stats gathering over night because I need to report the actual size of the table and its index immediately after the above operations. I think running DBMS_STATS.GATHER_TABLE_STATS may give me a more accurate usage data. I could be wrong though.
Thanks in advance,

In Oracle 11gR2 you still need to gather table statistics. I guess you read documentation for Oracle 12c, which automatically collects the statistics but only for direct path inserts, which is not your case, your insert is conventional. Also if you gather statistics (with default options) for brand new table that hasn't been used for queries no histograms will be generated.
Index statistics are gathered when index is built so it's not needed to gather its statistics explicitly. When you later gather table statistics you should use the DBMS_STATS.GATHER_TABLE_STATS option cascade => false so that index statistics aren't gathered twice.
You can simply check the statistics using
SELECT * FROM ALL_TAB_COL_STATISTICS WHERE TABLE_NAME = 'XXXX';

Related

Move Range Interval partition data from one table to history table in other database

We have a primary table that is Range partitioned by date with a 1-month interval. It's also a list sub-partitioned with 4 distinct values. So essentially it is one month partition having 4 sub-partitions.
Database: Oracle 19c
I need advice on how to effectively move the partition/sub-partition data from active schema to historical schema in another database.
Also, there are about 30 tables that are referenced partitioned on the primary table for which the data needs to be moved as well. Overall I'm looking to move about 2500 subpartitions
I'm not sure if an exchange partition would be the right approach in this scenario?
TIA
You could use exchange to get the data rapidly out of your active table, but you would still then to send that table over the wire to the remote history database to load it in.
In which case, using "exchange" probably is just adding more steps to the process for little gain. (There are still potential uses here depending on how you want to handle indexing etc).
But simplest is perhaps just transferring the data over, assuming a common structure between the two tables, ie
insert /*+ APPEND */ into history_table#remote_db
select * from active_table partition ( myparname )
I can't remember if partition naming syntax is supported over a db link, but if not, then the appropriate date predicates will do the same trick, and then just follow up with:
alter table active_table truncate partition myparname;

How to change table monitoring setting

I'm working on improving Oracle tables' performances.
The table that I have been working on created with 'monitoring' and 'logging' clause. These two, decreasing performance of query and I need to change monitoring to nomonitoring(without dropping tables).
This is working well:
alter table some_table nologging
But to alter monitoring to nomonitoring I use;
alter table some_table nomonitoring
query executes without any errors but there is no change in table structure.
I've been researching on internet for days and also as I saw here there is no such topic for my specific problem.
Thanks in advance.
The monitoring/nomonitoring options are deprecated and are no longer used in Oracle.
Quote from the Oracle 11.2 manual
Formerly, you enabled DBMS_STATS to automatically gather statistics for a table by specifying the MONITORING keyword in the CREATE (or ALTER) TABLE statement. Starting with Oracle Database 11g, the MONITORING and NOMONITORING keywords have been deprecated and statistics are collected automatically. If you do specify these keywords, they are ignored.
(Emphasis mine)

Populating Tables into Oracle in-memory segments

I am trying to load the tables into oracle in-memory database. I have enable the tables for INMEMORY by using sql+ command ALTER TABLE table_name INMEMORY. The table also contains data i.e. the table is populated. But when I try to use the command SELECT v.owner, v.segment_name name, v.populate_status status from v$im_segments v;, it shows no rows selected.
What can be the problem?
Have you considered this?
https://docs.oracle.com/database/121/CNCPT/memory.htm#GUID-DF723C06-62FE-4E5A-8BE0-0703695A7886
Population of the IM Column Store in Response to Queries
Setting the INMEMORY attribute on an object means that this object is a candidate for population in the IM column store, not that the database immediately populates the object in memory.
By default (INMEMORY PRIORITY is set to NONE), the database delays population of a table in the IM column store until the database considers it useful. When the INMEMORY attribute is set for an object, the database may choose not to materialize all columns when the database determines that the memory is better used elsewhere. Also, the IM column store may populate a subset of columns from a table.
You probably need to run a select against the date first

Sybase ASE 15.0.2 - dynamically update statistics/ index statistics

I am trying to update statistics to some of our tables whose names I receive as input to my procedure. But, I couldn't compile the procedure with the below code.
update index statistics #tableName
Aren't dynamic table names allowed? Or, would the below statement work?
select #statsCmd = 'update index statistics '+#tableName
exec(#statsCmd)
Also, what are the notable differences between "update statistics" and "update index statistics"?
It does appear that update statistics does not allow dynamic table names, but the second statement should work without issue.
Regarding update statistics & update index statistics:
Update statistics can be run against tables without indexes, and other non-index objects, as well as against indexes. If run against an index, it actually executes an update index statistics behind the scenes. Update index statistics only updates statistics for the indices on the specified table.
Also, have you looked into using the Job Scheduler, and the datachange function to automate your update statistics?

Is it safe to put an index on an Oracle Temporary Table?

I have read that one should not analyze a temp table, as it screws up the table statistics for others. What about an index? If I put an index on the table for the duration of my program, can other programs using the table be affected by that index?
Does an index affect my process, and all other processes using the table?
or Does it affect my process alone?
None of the responses have been authoritative, so I am offering said bribe.
Does an index effect my process, and all other processes using the table? or Does it effect my process alone?
I'm assuming we are talking of GLOBAL TEMPORARY tables.
Think of a temporary table as of multiple tables that are created and dropped by each process on the fly from a template stored in the system dictionary.
In Oracle, DML of a temporary table affects all processes, while data contained in the table will affect only one process that uses them.
Data in a temporary table is visible only inside the session scope. It uses TEMPORARY TABLESPACE to store both data and possible indexes.
DML for a temporary table (i. e. its layout, including column names and indexes) is visible to everybody with sufficient privileges.
This means that existence of the index will affect your process as well as other processes using the table in sense that any process that modifies data in the temporary table will also have to modify the index.
Data contained in the table (and in the index too), on the contrary, will affect only the process that created them, and will not even be visible to other processes.
IF you want one process to use the index and another one not to use it, do the following:
Create two temporary tables with same column layout
Index on one of them
Use indexed or non-indexed table depending on the process
I assume you're referring to true Oracle temporary tables and not just a regular table created temporarily and then dropped. Yes, it is safe to create indexes on the temp tables and they will be used according to the same rules as a regular tables and indexes.
[Edit]
I see you've refined your question, and here's a somewhat refined answer:
From:
Oracle® Database Administrator's Guide
10g Release 2 (10.2)
Part Number B14231-02
"Indexes can be created on temporary tables. They are also temporary and the data in the index has the same session or transaction scope as the data in the underlying table."
If you need the index for efficient processing during the scope of the transaction then I would imagine you'll have to explicitly hint it in the query because the statistics will show no rows for the table.
You're asking about two different things, indexes and statistics.
For indexes, yes, you can create indexes on the temp tables, they will be maintained as per usual.
For statistics, I recommend that you explicitly set the stats of the table to represent the average size of the table when queried. If you just let oracle gather stats by itself, the stats process isn't going to find anything in the tables (since by definition, the data in the table is local to your transaction), so it will return inaccurate results.
e.g. you can do:
exec dbms_stats.set_table_stats(user, 'my_temp_table', numrows=>10, numblks=>4)
Another tip is that if the size of the temporary table varies greatly, and within your transaction, you know how many rows are in the temp table, you can help out the optimizer by giving it that information. I find this helps out a lot if you are joining from the temp table to regular tables.
e.g., if you know the temp table has about 100 rows in it, you can:
SELECT /*+ CARDINALITY(my_temp_table 100) */ * FROM my_temp_table
Well, I tried it out and the index was visible and used by the second session. Creating a new global temporary table for your data would be safer if you really need an index.
You are also unable to create an index while any other session is accessing the table.
Here's the test case I ran:
--first session
create global temporary table index_test (val number(15))
on commit preserve rows;
create unique index idx_val on index_test(val);
--second session
insert into index_test select rownum from all_tables;
select * from index_test where val=1;
You can also use the dynamic sampling hint (10g):
select /*+ DYNAMIC_SAMPLING (3) */ val
from index_test
where val = 1;
See Ask Tom
You cannot create an index on a temporary table while it is used by another session, so answer is: No, it cannot affect any other process, because it is not possible.
An existing Index affects only your current session, because for any other session the temporary table appears empty, so it cannot access any index values.
Session 1:
SQL> create global temporary table index_test (val number(15)) on commit preserve rows;
Table created.
SQL> insert into index_test values (1);
1 row created.
SQL> commit;
Commit complete.
SQL>
Session 2 (while session 1 is still connected):
SQL> create unique index idx_val on index_test(val);
create unique index idx_val on index_test(val)
*
ERROR at line 1:
ORA-14452: attempt to create, alter or drop an index on temporary table already in use
SQL>
Back to session 1:
SQL> delete from index_test;
1 row deleted.
SQL> commit;
Commit complete.
SQL>
Session 2:
SQL> create unique index idx_val on index_test(val);
create unique index idx_val on index_test(val)
*
ERROR at line 1:
ORA-14452: attempt to create, alter or drop an index on temporary table already in use
SQL>
still failing, you first have to disconnect session 1 or table has to be truncated.
Session 1:
SQL> truncate table index_test;
Table truncated.
SQL>
Now you can create the index in Session 2:
SQL> create unique index idx_val on index_test(val);
Index created.
SQL>
This index of course will be used by any session.

Resources