Thursday, August 31, 2017

Turboboost your Database Import!


Related image

Unfortunately there is no Turbo Boost button on the oracle import data pump utility (impdp) and for that matter the same would apply to the rest of the oracle suite of products and most technologies that we use today. This is why we have Oracle DBAs, Architects, Engineers and amazing problem solvers that can work to optimize and tune processes!

In my case I did an export of a large 12c  12.1.0.2 version test database that is using the application JD Edwards Enterprise One version 9.2 . The size of the database is about 2.6TB. The hardware is an Oracle engineered system the ODA X5-2. The database compute node has 1 single CPU socket with 24 cores.



I used the following export data pump parameters in my par file.

cluster=N
compression=ALL
directory=EXPORT_DP
dumpfile=export_jdeprod_schemas_%u.dmp
filesize=20G
FLASHBACK_time=systimestamp
logfile=export_dump_jdeprod_schemas_log.log
parallel=8
schemas=PRODCTL,PRODDTA
content=ALL

The export data pump process took only a short duration of 33 minutes and the total size of the compressed export dump files was 67GB.

I was requested by my client to refresh the two schemas I exported PRODCTL and PRODDTA. I simply dropped and recreated the users from the user creation DDL scripts I had saved prior. This method is the cleanest way I know to do a refresh of a full schema which is the process I normally use.

I then proceeded to create the import parameter file as follows:

userid='/ as sysdba'
Directory=EXPORT_DP
Dumpfile=export_jdeprod_schemas_%U.dmp
Parallel=10
Logfile=impdp_jdeprod_schemas_copy1.log
schemas=proddta:prodctl

Looks straightforward right? Please note the parallel 10 setting which I thought would help on the overall import process. The import process actually ran for a whopping 32 hours and 15 minutes which is basically 1 day and 8.25 hours! This import duration was completely unacceptable especially after doing an export that only took about 33 minutes to run. As I monitored the import process I quickly realized that the majority of the time the import spent on was the index and constraint builds. 

I knew from experience all indexes are normally created in single threaded mode using the default attribute setting of parallel 1. Note in most cases the parallel attribute is not altered for indexes to something other than 1 otherwise if it was something greater when the export was done then the index would definitely be created with the same parallel degree on the import process. Next I worked on creating an SQL DDL script file for the indexes and constraints. My plan would be to run the import process without creating the indexes and constraints, it would just create and load the tables only. The following is the command to run to create a SQL DDL script file for the indexes and constraints.

$ impdp sqlfile=index_constraint_script.sql include=INDEX,CONSTRAINT


Once the above command completes then you will need to modify the index_constraint_script.sql file and replace all occurrences of parallel 1 to something higher such as parallel 12. In my case all indexes had a parallel degree of 1.

The following modified import parameter file is what I used. This new parameter file does not create indexes or constraints, it just creates the tables and load the data into it. Note the parameter TRANSFORM=DISABLE_ARCHIVE_LOGGING:Y, it is quite helpful and what this parameter does is reduce the overall redo logging operations by creating the tables in no logging mode. Keep in mind this parameter does not help if the database is already in force logging mode. I also suggest to set the logtime parameter to be set to all so you can see the timestamp as the import log is written to.

-- Import parameters for Tables only
userid='/ as sysdba'
Directory=EXPORT_DP
Dumpfile=export_jdeprod_schemas_%U.dmp
Parallel=10
Logfile=impdp_jdeprod_schemas_copy1.log
TRANSFORM=DISABLE_ARCHIVE_LOGGING:Y
logtime=all
schemas=proddta:prodctl
EXCLUDE=INDEX,CONSTRAINT

Before I reran the import again for a second time I dropped both of the schemas from the database and recreated them. This time when I ran the import process it completed in about 1 hour. The import only created the tables and loaded the data into the tables since I am excluding the index and constraint creation.

Next you may then invoke the SQL script file that was just created and also ensure you create a spool file then set timing on to see the elapsed time for each statement in the log file. I would suggest running the script in nohup mode as follows:

$ nohup sqlplus '/ as sysdba' @index_constraint_script.sql &

The script to create the indexes in parallel mode for each index and to also create the constraints took about 10 hours so the whole process to do the import and index/constraint creation took about 11 hours. Overall we went from 32.25 hours down to 11 hours which is about a 66% decrease change of improvement! The total duration improved by more than half and it was nice to see this. Please note another tip you can also split the index script into parts and run them in parallel for even a faster execution of the index builds.

Some additional items I did from a database tuning perspective to help were the following based on AWR report findings from the prior import run.
  • Increased the redo log size from 1G to 3GB and created 5 groups instead of 3. This was done to reduce the log file sync waits.
  • Increased the PGA_AGGREGATE_LIMIT from 2GB to 24GB to help reduce overall sorting operations when building the indexes.
  • Increased the PGA_AGGREGATE_TARGET from 2GB to 12GB to help reduce overall sorting operations when building the indexes.
  • Increased the SGA_TARGET from 4GB to 12GB to help reduce the I/O physical reads from disk.
UPDATE Oct 10, 2017 -

I have an additional update that can be used to help optimize the process even further. I was able to optimize the constraint creation process in parallel as well and shave off about by another 7 hours! So now the entire import process went from about 32.25 hours down to about 4 hours of duration this is about a 88% decrease change in improvement now! I like that.

Here is what you need to do to optimize the constraint creation process.


  • Separate the file index_constraint_script.sql into two files one for the indexes and one for the constraints.
  • Enable a parallel degree on all tables in the tables you need to import into such as a degree of 12.
  • Then again split the constraints script into two files again.
  • The first of the constraint file should only have the following command to create the constraint with the novalidate clause. This will create the constraint instantly, an example is below.
ALTER TABLE "OWNER"."TABLE_NAME" ADD CONSTRAINT "PK1" PRIMARY KEY ("COL1", "COL2") USING INDEX "OWNER"."IX1"  ENABLE novalidate;
  • Enable parallel DDL in the same session prior to running the following step.
ALTER SESSION ENABLE PARALLEL DDL;
  • The second constraint file should have the following syntax. This will allow the constraint to be  created in parallel by checking for the parallel degree on the table/index.
alter table OWNER.TABLE_NAME enable constraint PK1;

Also I was told by a colleague that there is an oracle patch which supposedly is supposed to help doing the index and constraint creation in parallel. You may reference the following My Oracle Support notes below. I can only confirm the patch helps to parallelize the index creation but not the constraint creation.


Why Isn't Datapump Creating Multiple Indexes in Parallel? (Doc ID 402511.1)

Patch 22273229: IMPDP DOES NOT USE PARALLEL LOAD FOR PRIMARY KEY


I hope my experience helps others optimize their import process. A wishlist item I have for a future release of oracle would be to allow to set in the import parameter file the parallel degree for the index creation. This would be a major help for a faster import!



Sunday, July 9, 2017

Registration of an 11.2 database fails against a 12.1 CRS stack

I encountered a problem while registering an 11gR2(11.2.0.3) standby database against a 12.1 CRS stack home. See the add database command and the failure afterwards.

$ srvctl add database -d prod01 -o /prd/prod01/product/11.2.0/db_1  -p '+PROD01_DATA/prod01/spfileprod01.ora' -r PHYSICAL_STANDBY -s MOUNT -y AUTOMATIC -t IMMEDIATE -a 'PROD01_DATA,PROD01_FRA,PROD01_REDO'

PRCR-1006 : Failed to add resource ora.prod01.db for prod01
PRCD-1184 : Failed to upgrade configuration of database type to version 11.2.0.3.0
PRCR-1071 : Failed to register or update resource type ora.database.type
CRS-0245:  User doesn't have enough privilege to perform the operation


I was surprised to see this problem and luckily there is an MOS support note on this issue that is well documented with a workaround or patch that can be applied.

The workaround to the issue is run the following after setting your environment to the 12.1 CRS home.

$ crsctl modify type ora.database.type -attr  "ATTRIBUTE=TYPE_VERSION,DEFAULT_VALUE=3.2" "-unsupported"
$ crsctl modify type ora.service.type -attr "ATTRIBUTE=TYPE_VERSION,DEFAULT_VALUE=2.2" "-unsupported"


A one-off patch also exists and the fix is included in 11.2.0.3.4 GI PSU onwards.

Patch 13460353: REGISTRATION OF 11.2.0.3 DATABASE FAILS AGAINST 12.1 CRS STACK

Wednesday, May 31, 2017

Oracle Data Guard Timezone Considerations

I got a question from a client about Oracle Data guard timezones requirements. They asked if the timezones on the Primary and Standby servers need to be the same or not? The first thing that came to mind is that from my experience it simply does not matter at all. For example if your Primary Database server is in Chicago(Central time) and your Standby Database server is in New York(Eastern time) then you should not have any issues with log shipping replication. 

I was talking to an Oracle consultant on the topic today and he pointed out that the Oracle documentation actual does recommend that BOTH Primary and Standby Database servers should consider having the same timezone. This was something I learned new about Data guard.

Check out the verbiage from the 12c documentation, Data guard Concepts and Administration guide. That came as 

https://docs.oracle.com/database/121/SBYDB/standby.htm#SBYDB4717

"Because some applications that perform updates involving time-based data cannot handle data entered from multiple time zones, consider setting the time zone for the primary and remote standby systems to be the same to ensure the chronological ordering of records is maintained after a role transition."

Based on this information it perhaps would be a good idea to consider using one standard timezone for database servers in a Data guard configuration such as the GMT or the UTC+0 timezone. Keep in mind before considering this standard that you would need to check if your specific application cannot handle data entered from multiple time zones, if this is the case then consider using the same timezone for your Database servers in the Data guard configuration. One another option workaround would be to ensure the timezone data is recorded from the application as the data is recorded into the database, this configuration would allow different time zones for the database servers in a data guard configuration and should not present any issues after a role transition.








Friday, March 17, 2017

How to backup the Oracle Supercluster M7 system?

Backing up the Oracle Supercluster M7 system is critical a task that should completed upon the system deployment. Having a good backup & recovery plan is a vital standard practice that is of utmost importance. I highly recommend that any backup/recovery plan always be tested on a regular basis to ensure it is working for your system environment.

Oracle Solaris has provided a tool that will backup & restore critical components of an Oracle Supercluster back together again. The osc-config-backup tool make the process of backing up the SuperCluster component configurations simple. The backup data is then stored on the internal ZFS storage appliance that is on the Supercluster system.

The following a link to the Supercluster M7 osc-config-backup tool link and an Oracle Support note with more details on the tool.

https://docs.oracle.com/cd/E58626_01/html/E69073/z400020e165586.html#scrolltoc

How To Back Up the Oracle SuperCluster Configuration with osc-config-backup (Doc ID 1934129.1)

Currently the osc-config-backup tool is supported on the Oracle SuperCluster M7 and Oracle SuperCluster T5-8.

The following SuperCluster components are backed up by osc-config-backup:
·       Domains – Configuration, ZFS pools (rpool, bpool if present, and u01-pool for Database Domains)
·       Oracle Solaris zones – Configuration, ZFS pools (rpool and u01-pool for Database Zones)
·       IB switches – Configuration
·       Ethernet management switch – Configuration
·       ZFS storage appliance – Configuration
·       SuperCluster – Configuration information (ssc-cu.zip file)
·       Service Processor – Configuration
·       Explorer – Data from each Database and Application Domain

Please note: Data located outside the rpool and u01-pool zpools in zones and domains is not backed up by osc-config-backup


You still should do regular file system level backups as you would any other system to backup other critical filesystems and their contents. Any file level backup tool that you would use to back up any other system should suffice.

Finally, to recover from the backup from the tool. Please refer to the following Oracle Support note.

How To Recover SuperCluster Components that were Backed Up with osc-config-backup (Doc ID 1934130.1)

Thursday, February 23, 2017

Memory Script I/O Domain Solaris

The following script is useful to see the memory information on an I/O Domain on Solaris. I have used this script on an M7 Supercluster deployment on Solaris 11. You can see the total available memory, free memory and the used memory.

#!/usr/bin/ksh

# Available memory
memory=`prtconf | grep Memory | head -1 | awk 'BEGIN {FS=" "} {print $3}'`
gb_memory=`echo "scale=2; $memory/1024" | bc -l`

# Free memory
pagesize=`pagesize`
kb_pagesize=`echo "scale=2; $pagesize/1024" | bc -l`
sar_freemem=`sar -r 1 1 | tail -1 | awk 'BEGIN {FS=" "} {print $2}'`
gb_freemem=`echo "scale=2; $kb_pagesize*$sar_freemem/1024/1024" | bc -l`

# Used Memory
gb_usedmem=`echo "scale=2; $gb_memory-$gb_freemem" | bc -l`

# Conclusion
echo "Avai Mem: $gb_memory GB"
echo "Free Mem: $gb_freemem GB"
echo "Used Mem: $gb_usedmem GB"


Sample Output below:
--------------------------


$ free.sh
Avai Mem: 96.00 GB
Free Mem: 42.02 GB
Used Mem: 53.98 GB






Sunday, December 4, 2016

Oracle Dataguard Deep Dive Presentation

Thank you to the Dallas OUG for letting me present recently on my "Oracle Dataguard Deep Dive" topic. I also covered 12c new features as well in this presentation. You may view my presentation at the following link.

http://tinyurl.com/hq5h7s3

Wednesday, September 14, 2016

Important Settings on Every Oracle Database Build!

Today I worked on a problem on an Oracle Supercluster M7 system. The issue was that we have about 15 databases running from a single I/O DB Domain it is basically a Virtual Machine(VM). The total allocated SGA/PGA memory across all of these 12c(12.1.0.2) databases was set to a total sum of 60GB and the whole VM has 192GB of memory assigned to it however when I checked the free memory I only showed about 3-4GB available. This did not make sense at all and it did not add up since I only allocated 60GB across all databases. A few issues that we experienced other than the limited memory was also that we got consistent related errors as a result of the limited memory across the database alert logs.

ORA-00604: error occurred at recursive SQL level 1
ORA-04031: unable to allocate 128 bytes of shared memory
ORA-00700: soft internal error, arguments: [kskvmstatact: excessive swapping observed]
ORA-27300: OS system dependent operation:fork failed with status: 12
ORA-04030: out of process memory when trying to allocate 552 bytes (kxs-heap-p,kxfqlobf)


BTW Please keep in mind this issue can also apply to other systems as well such as Exadata, a Physical server or any VM running oracle databases.

I started to dig and troubleshoot.

prstat -t output below shows total memory usage by user on Solaris. Look at the RSS column below it clearly shows 144GB of memory being used by the oracle user. I was surprised to see this.

NPROC USERNAME SWAP RSS MEMORY TIME CPU 
85 root 2520M 2481M 1.3% 87:40:45 0.2% 
5462 oracle 183G 144G 75% 197:27:56 0.2% 
51 grid 17G 12G 6.4% 34:47:13 0.0% 
1 smmsp 4272K 10M 0.0% 0:00:06 0.0% 
7 daemon 9384K 12M 0.0% 0:00:54 0.0% 
1 netcfg 4344K 7240K 0.0% 0:00:24 0.0% 
3 netadm 46M 46M 0.0% 0:00:45 0.0% 

I then wanted to see a list of process sorted by memory usage I also added cpu time, the process id and the command and sorted by the memory column from largest usage to lowest as shown in the following command. The output showed that the largest processes were oracle and all of them were about the same size based on the pmem column which shows the output in terms of a %.

# ps -eo pmem,pcpu,pid,comm | sort -k 1 -nr |wc -l 

I also wanted to see a total process count on the server so I ran the following command it returned about 6000 processes, so many.

# ps -ef| wc -l

..And the plot thickens then I thought about checking to see if we have too many parallel process threads running and I ran the following command to check and verify this.The following command returned about 4800 rows! Now we are on to something this clearly shows that about 80% of the processes running on the VM are all parallel threads, this is way to much.

ps -eo pmem,pcpu,pid,comm | sort -k 1 -nr |grep -i _p0|wc -l 

The parallel_max_servers database init parameter in 12c is a culprit for this and it should be limited. If this parameter is not set it will take the default value which is based upon the settings from CPU_COUNT, PARALLEL_THREADS_PER_CPU, and PGA_AGGREGATE_TARGET. 

The CPU_COUNT database init parameter should also be limited as well. If the default value is taken then the database will take upon the value reported by the total cpu threads reported from the OS. In my case we have 20 CPU cores assigned to the VM and on the M7 Supercluster each CPU has 32 cores with 8 threads each a total of 256 threads per core.So 20 cores assigned to the VM is 160 threads and can set CPU_COUNT accordingly based on the workload need.

The PARALLEL_THREADS_PER_CPU is normally OS dependent and usually 2. This setting is fine.

Once I appropriately set the CPU_COUNT and PARALLEL_MAX_SERVERS parameters on each of the 16 databases and restarted each one I was happy to see the overall memory utilization dramatically decreased. As shown below in the prstat command.

# prstat -t 
NPROC USERNAME SWAP RSS MEMORY TIME CPU 
764 oracle 80G 56G 29% 14:33:54 0.1% 
94 root 2525M 2493M 1.3% 88:14:08 0.1% 
53 grid 8239M 6759M 3.4% 34:26:20 0.0% 
1 smmsp 4272K 10M 0.0% 0:00:06 0.0% 
7 daemon 9384K 12M 0.0% 0:00:55 0.0% 
1 netcfg 4344K 7240K 0.0% 0:00:24 0.0% 
3 netadm 46M 46M 0.0% 0:00:45 0.0% 



In Summary the following two parameters should be set appropriately on every new Oracle Database build. As a best practice please limit these parameters as the default settings could hurt the overall performance of your system and even impact the available memory as it did in our case. I have even see many cases where the PARALLEL_MAX_SERVERS was not set and it completely hung an Exadata or other types of database servers so please be mindful of these two parameters.


  • CPU_COUNT
  • PARALLEL_MAX_SERVERS