Disaster Recovery and Other Sacrifices

If you desire a subject that will invoke deep passion and
often combined with disgust from a group of DBA’s, disaster recovery is the
one.  It is the subject that rarely we
feel our butts are not out there hanging, no matter how much we’ve attempted to
secure our environment.

payday loans lenders online

I’ve observed a consistent flow of articles, conversation
and email discussions on the subject and it is apparent that rarely is the
business as aware as the technical specialists, (aka the DBA) of just how
vulnerable their environments are.  Rarely
are the budget dollars allotted to the task of insuring that systems have the
proper disaster recovery hardware/software in place and/or testing performed in
a regular basis.

It’s easy for the business to see the value in the
production systems.  They create revenue
and their value is equal to the dollars they produce.  Development and test are more difficult for
them to understand, but most times, they can be justified the first time
production is undermined due to development or testing being performed in one
of them…:)

We now get into backup and recovery.  How many backups are impacted by 24X7 shops,
where the only thing viewed by the business is impact to revenue by having to
allocate resources to backing up production and placing it on disk/tape that
offers them no value to that revenue.
Yes, the DBA’s and technical management argue, “All it takes is one loss
of production and you will be thankful that we have that backup…”  Until that day comes, many business’ rely on
the robust nature of Oracle, the hardware it resides on and the technical
expertise of the folks they’ve hired to keep it running and never having to
rely on those backups.   DBA’s commonly fight on a regular basis for time
to allocate to testing, hardware to test recoveries to and explaining to the
business why it’s important.  The
business again looks on this as time that could be better allocated to creating
faster systems to create more revenue and again, impact to what the business is
there for- creating revenue.

The next level is then disaster recovery.  All DBA’s know this is the final
gauntlet.  We pray to the DBA Gods hoping
for a technical manager with the gift to motivate, sell and help the business
to understand why having standby’s of production databases to keep revenue
flowing in case of primary production going down is important.  We are willing to sacrifice small animals in
the name of a secondary data center for disaster recovery testing.  We want to know how long the business will be
down in case the unthinkable does happen and if all the documentation on what
it takes to create production will actually work when we do try to recreate it.  We would also like to have that answer
demanded of us when the unthinkable does happen and upper management is sitting
in front of us asking, “So HOW long are we down for???”

This is not rare, this is not uncommon, it is all too often
the norm for most DBA’s in the business world.
IT Managers, Network Administrators, Database Administrators often
battle day in and day out, not just for what they need to provide the growing
demands of the business, but what the business needs to survive in case of
disaster.  Our jobs are not just to
provide you with production, but to provide you with an ability to sustain your
business when the unthinkable happens.

Tempfile Read /Writes and ASM

I truly believe that database myths are the scourge of the database world.  With that said, I have to blame myself for not being specific enough in one of my own blog posts and propagating one myself!  As it was brought to my attention by Tanel Poder and Greg Rahn, I hadn’t put a post out here until now, so apologies!

I have flipped back to an almost exclusively 10g environment the last three months, but even though I’m back to my old stomping grounds, now fully staffed with almost double the DBA’s that were present when I left, have been able to implement ASM.  With this change, I also need to update my data on how tempfiles are written to.  When you read my blog on temp usage in parallel, in must be reminded that this post is for a Non-ASM environment.  I also think for those that have high waits in temp read and writes, this should be an extra selling feature of ASM.

ASM, when implemented in any Oracle environment, 10g, included, will change the way that tempfiles are written to.  Instead of single file writes, even when multiple tempfiles per a temp tablespace are present, with ASM, it WILL stripe across the files efficiently, (unless statistics are in issue) with parallel.  There would then only be the benefit of having multiple temp tablespaces if you would like to allocate a different temp tablespace to different processes, but even then, the performance gain was marginal in my tests.

I did receive similar performance gains of temp tablespace groups without ASM as a single temp tablespace with multiple files with ASM.  I was only able to gain extra performance when spreading heavy hitting temp usage across temp tablespace groups during high concurrency situations.   the overall performance gain was only 12%, which was no where near what I experienced in the Non-ASM environment choice to go to temp tablespace groups with parallel processing.  These were processes that utilized over 50GB of temp per parallel process.

I still have processes that limit my tuning options that have me daydreaming about multiple temp tablespace groups on multiple ASM groups, residing on SSD, but again, I’m daydreaming … :)

A Tale of Session Parameter Settings

This is another blog post about how TEMP can kill you in performance.

The Program Global Area, aka PGA, is a memory region that allows Oracle to perform many processes that once fell to static calculations in parameters that had to be managed by a DBA.

As frustrating as it might be to a DBA to not have enough memory to allocate to the performance enhancing feature, I found it even more frustrating to find NO PGA allocation to window sorts.  We were experiencing poor performance in one of our environments, but I noted it was only during heavy workloads, resulting from heavy IO, NO execution plan changes, but outrageous waits on temp reads and writes.

db file sequential read   61,275,579   161,054      44.7   User I/O
direct path read temp     17,262,132    74,398      20.6   User I/O  <--TEMP is on SSD!!
CPU time                                71,971      20.0
direct path write temp    10,572,848    38,611      10.7   User I/O  <--TEMP is on SSD!!

 

Upon querying the work area, I discovered the following:

select vst.sql_text, swa.sql_id, swa.sid, swa.tablespace
, swa.operation_type
, trunc(swa.work_area_size/1024/1024) "PGA MB"
, trunc(swa.max_mem_used/1024/1024)"Mem MB"
, trunc(swa.tempseg_size/1024/1024)"Temp MB"
from v$sql_workarea_active swa, v$session vs, v$sqltext vst
where swa.sid=vs.sid
and swa.sql_id=vs.sql_id
and vs.sql_id=vst.sql_id
and vst.piece=0
order by swa.operation_type;

SQL_ID Temp Tablespace Operation Type PGA SGA TEMP
09am9sr9uca5y TEMP_4 WINDOW(SORT)

0

0

1375

09am9sr9uca5y TEMP_1 WINDOW(SORT)

0

0

1405

09am9sr9uca5y TEMP_2 WINDOW(SORT)

0

0

1415

09am9sr9uca5y TEMP_3 WINDOW(SORT)

0

0

1420

 

The process in question, as most processes in the database environments I work in was parallel, (degree 4) working with temp tablespace groups, (count of 4) on SSD, so quite fast, but to see this amount of processing “swapping” to temp was frustrating and painful to performance.

The IO was killing the performance, even with this running on SSD, we were 100% saturated on the disk!:

Device:       reads/s            writes/s              rsec/s                    wsec/s                  %util

Fio1              1584.00          1460.33                 101397.33            129344.00           73.97

Fio2              1603.33          1534.67                 102720.00            134776.00         100.03

 

FROM AWR:

%Time Total Wait wait Waits

Wait Class                      Waits  -outs         Time (s)    (ms)      /txn
-------------------- ---------------- ------ ---------------- ------- ---------
User I/O                   91,531,087     .0          279,954       3  56,223.0
Other                       4,067,544    2.9           12,718       3   2,498.5

Now where the key came in was the rest of the parallel processes when looking at their allocation:

SQL_ID Operation Type PGA SGA TEMP
09am9sr9uca5y   HASH-JOIN

511

23

09am9sr9uca5y   LOAD Write Buffers

0

0

09am9sr9uca5y   HASH-JOIN

511

23

09am9sr9uca5y   HASH-JOIN

511

23

Now even though the PGA is set to 32G and the allocating to numerous other processes, this one appeared very “odd” and why it’s the key the PGA.  Consider what the overall process would have to be to allocate 511 MB of PGA to the three processes above.   This would mean that 500MB was allocated to the process and then there was the approximate 10MB overhead.  The number was too evenly distributed and too high and no PGA was allocated to two newer features to 10g, such as analytical functions, (window sorts) .

I remembered that at one time, this company had a developer employed to it that had a penchant for the following manual session alteration:

EXECUTE IMMEDIATE 'ALTER SESSION SET WORKAREA_SIZE_POLICY = MANUAL';
EXECUTE IMMEDIATE 'ALTER SESSION SET SORT_AREA_SIZE = 536870912';
EXECUTE IMMEDIATE 'ALTER SESSION SET HASH_AREA_SIZE = 536870912';

 

Upon a search of the code, it was found that this was in the main package, but:

  1. The beginning procedure which executed from the package was actually in the center of the package, so developers never noted it as being an issue and the DBA’s never dug into the code deep enough before to know this manual alteration was present.
  2. Due to a huge process change to how the code produced work, there had been a large insertion of analytical functions that caused the performance degradation upon heavy loads.

The testing process was simple.

  1.  Removed the three lines from the initial procedure in the package.
  2. Run the same heavy load of processing from production in test with the new code.

Change in how the PGA is allocated:

SQL_ID Temp Tablespace Operation Type PGA SGA TEMP
09am9sr9uca5y TEMP_2 WINDOW (SORT)

26

95

598

09am9sr9uca5y TEMP_3 WINDOW (SORT)

26

95

598

09am9sr9uca5y TEMP_1 WINDOW (SORT)

26

95

598

09am9sr9uca5y TEMP_4 WINDOW (SORT)

26

95

598

I also found the PGA savings to the hash joins interesting, as what was statically “forced” in the manual allocation wasn’t what the database really required and was simply wasted with the old settings, where the PGA dynamically set much smaller amounts:

SQL_ID Temp Tablespace Operation Type PGA SGA TEMP
12bhautka6mvp LOAD WRITE BUFFERS

0

0

12bhautka6mvp HASH-JOIN

2

1

12bhautka6mvp HASH-JOIN

2

1

12bhautka6mvp HASH-JOIN

2

1

12bhautka6mvp HASH-JOIN

2

1

Result:

Increase in performance:  7 fold

The fix was moved to production that day, without hesitation and everyone shook their head as to why this was ever put into place by anyone,  but I want to follow up on that question that many folks, I’m sure have.  Although I do not support this, especially in 10g and 11g databases due to what we see here, you do have to understand what the developer’s goal was:

The developer :

  1.  Saw benefits to straight 500MB allocation of PGA to processing that over-rides the percentage allocation maximum per process.
  2. Experienced huge gains in performance on hash joins due to this change and we did suffer some small performance hits when it was removed, but the overall performance gain was still outstanding!
  3. Wasn’t aware of future enhancements and code changes that would have been vulnerable to his choice in coding session parameter changes.

 

Warp Speed with Temp Tablespace Groups

The introduction of the temp tablespace was a crucial step in the RDBMS to separating  the “work area” for sorting and specific join operations from permanent segments.   To eliminate the performance challenges of sorts and hash against the I/O threshold involved with performing this word in the temp tablespace, Oracle 9i introduced the Program Global Area, (PGA) to complete sorts and hashes within memory.

DBA’s spent considerable time tuning the PGA, attempting to continually ensure that as more complex sorting and join features emerged, that these processes would complete their work within the PGA and not require such a large work area to force a, “swap” to the temp tablespace, again returning to an I/O bound process.

Throughout the years of 10g release 2, larger databases, required more sorting and hash operations, which in turn required larger work areas that for particular requirements, no PGA could meet.  This would be seen in PGA cache hit graphs without a size recommendation to meet a 90% or better hit ratio.  These sorting and/or hash “heavy” processes would then become burdensome on the database, often encompassing the primary utilization of temporary “swap” and extended wait time.

 

When a DBA or Developer observes high waits on tempfile reads and writes, the challenge is often not understood.  Unlike a standard tablespace, that with high read and writes can have the I/O intensive demands spread across more area by adding multiple datafiles to write to simultaneously, a temp tablespace, when observed, will appear very different.

A simple ASH report can show how impacting this type of performance challenge can be to a VLDB:

 

Event

% Event

P1 Value, P2 Value, P3
Value

% Activity

Parameter 1

Parameter 2

Parameter 3

direct path read temp

43.27

“1001″,”3502″,”7″

0.01

file number first dba block cnt
PX Deq Credit: send blkd

26.18

“268501001″,”2″,”0″

1.50

sleeptime/senderid passes qref

“268501001″,”1″,”0″

1.18

“268501003″,”2″,”0″

1.06

direct path read

5.10

“50″,”11333″,”11″

0.01

file number first dba block cnt
direct path write temp

1.47

“1003″,”50949″,”7″

0.01

file number first dba block cnt

 

SQL ID

Planhash

% Activity

Event

% Event

SQL Text

dhytpraqah5c5

2880106315

100.00

direct path read temp

43.27

create table report_tbl1…
PX Deq Credit: send blkd

26.18

 

Temp tablespace groups have received little press and less discussion since their introduction in Oracle 10g.  When utilizing temp tablespace groups, a DBA can offer impressive performance increases by spreading the I/O across multiple files vs. one tempfile.   As tempfiles are utilized differently than datafiles, a temp tablespace group enables a process to consume temp space from multiple tablespaces.

Before the feature is implemented though, there are many considerations that need to be examined to ensure that benefits are seen and that complications are not introduced.

 

Myths about temptablespace groups:

Myth 1.  A temp tablespace group must have more than 1 tablespace.

Answer-  Untrue.  The tablespace group is created with the initial temp tablespace defined with the temp tablespace group clause.

 

Myth 2.  There is a limit to how many temp tablespaces can be added to a temp tablespace group.

Answer-  There is no explicit limit on the maximum number of tablespaces that can be allocated to a tablespace group.

 

Myth 3.  A temporary tablespace can belong to more than one temporary tablespace group.

Answer-  It can belong to only one group.

 

Myth 4.  Temporary tablespace groups improve all sorting issues.

Answer-  Windows sort rank often perform worse when utilizing temp tablespace groups and parallel.

The feature can be allocated to one user as its temporary tablespace or to an entire database to increase performance.

 

To create a temporary tablespace group is quite simple:

CREATE TEMPORARY TABLESPACE <tablespace_name>
TEMPFILE <ASM DISKGROUP >
SIZE <SIZE REQ>
TABLESPACE GROUP <group_name>;
CREATE TEMPORARY TABLESPACE TEMP_G1
TEMPFILE '+DATA'
SIZE 20000M
TABLESPACE GROUP TEMP_G;
desc dba_tablespace_groups

 

SELECT *
FROM dba_tablespace_groups;
ALTER TABLESPACE <tablespace_name>
TABLESPACE GROUP <group_name>;
ALTER TABLESPACE DM_DATA1 TABLESPACE GROUP TEMP_G;
ALTER USER DM_USER TEMPORARY TABLESPACE TEMP_G;
SELECT TEMPORARY_TABLESPACE FROM DBA_USERS
WHERE USERNAME='DM_USER';
ALTER SYSTEM TEMPORARY TABLESPACE TEMP_G;

 

Planing to implement temp tablespace group(s)
1.  Plan your temp tablespace group with careful consideration-  the tablespaces should be of the same size, have the same amount of files with the tempfiles each the same size.
2.  Keep in mind- inconsistent sizes across the tablespaces can affect the efficiency of the striping when using a non-ASM managed environment.
3.  The temp work will stripe across the tablespaces quite evenly.  When using a temp tablespace group, it will no longer simply use one temp tablespace at a time, so keep this in mind when monitoring temp tablespace usage.
4.  If in a non-ASM environments, stripe your files in differing orders to avoid having the same # file on the same drive as another temp tablespace from the temp tablespace group-  this will eliminate more I/O “hot spots”.
4.  You should estimate the required size of each tablespace to be approximately 40-60% or your current temp tablespace needs, depending on your database usage, (parallel processing, rowid range scans and types of sorts…)
5.  Temp tablespace groups should not be a replacement for SQL tuning. Larger than acceptable temp tablespace usage in correlation to the data set size the code is working with is a clear indicator that the code should be examined for tuning opportunities.

6.   Match your quantity of temp tablespaces contained in a tablespace group to the amount of parallel you will be hinting in your statements using it.

7.   Poor performance from statistics issues is only aggravated by temp tablespace groups.  Sort and hash operations are two of the most sensitive tasks to poor statistics, so it is easy to understand that extensive performance issues should be expected if statistics are not addressed before temp tablespace group introduction.

 

Temp tablespace groups and parallelism

DBA’s who utilize parallel query efficiently in their environments often follow a strict set of guidelines on what scenarios, objects and design must be in place before parallel will offer a true benefit in performance.

  • Partitioned Objects
  • Where clause that utilizes a partitioning key.
  • Large insert/update with defined variables.
  • Non-stale statistics
  • Setting the degree of parallel, (DOP) on the object.

Parallel can be utilized with temp tablespace groups to enhance performance to an incredible degree as well, but of the above “rules”, only one is preferable and it is most likely not the one most would guess from the above list.

Temp Tablespace groups should have the following for positive performance gains when utilizing parallel:

  • Non-stale statistics
  • Set the degree of parallel, (DOP) as a hint in the query, not at the object level.
  • Combination works best with OLAP and DSS systems, rare occasion where an OLTP would benefit.
  • Unless the insert and update is performing large sort or hash, it would offer little performance gain.
  • Partitioned objects are not a requirement to receive performance benefit.

The last bullet point is often difficult to understand, but the mindset must be re-aligned from the idea that you are using parallel to benefit a “read or write on multiple objects” i.e partitioned objects and that we are using the parallel process to benefit “read and write to multiple tempfiles” which is the temp tablespace group.  Visualizing the temp tablespace group as a “partitioned object” may assist with comprehending the benefits.

 

Performance Example

The process example:

  • utilizes 720GB of temp tablespace.
  • has an execution time of 16 hrs.
  • Source tables are 472GB in a 10TB datamart environment.

The Goal to attain:

  • Cut the execution time in 1/2 to re-allocate the resources to other processes.
  • Minimize temp usage by 60%.
  • Use temp tablespace groups to eliminate temp read/write waits in existing process.

Note**  Second time documenting this test.  Current iteration has enhancements (i.e. Added fourth temp tablespaces and changing amount of parallel used in the statements, etc…)

Create Temp Tablespace Group, three temp tablespaces total, 150GB each-
 CREATE TEMPORARY TABLESPACE TEMP_G1 TEMPFILE ‘/u06/oradata/sid1/temp_g1_01.dbf’ SIZE 51200M,
 ‘/u10/oradata/sid1/temp_g1_02.dbf’ SIZE 51200M,
 ‘/u20/oradata/sid1/temp_g1_03.dbf’ SIZE 51200M
 TABLESPACE GROUP TEMP_G;
CREATE TEMPORARY TABLESPACE TEMP_G2 TEMPFILE ‘/u30/oradata/sid1/temp_g2_01.dbf’ SIZE 51200M,
 ‘/u20/oradata/sid1/temp_g2_02.dbf’ SIZE 51200M,
 ‘/u10/oradata/sid1/temp_g2_03.dbf’ SIZE 51200M;
 ALTER TABLESPACE TEMP_G2 TABLESPACE GROUP TEMP_G;
CREATE TEMPORARY TABLESPACE TEMP_G3 TEMPFILE ‘/u25/oradata/martd/temp_g3_01.dbf’ SIZE 51200M,
 ‘/u10/oradata/martd/temp_g3_02.dbf’ SIZE 51200M,
 ‘/u04/oradata/martd/temp_g3_03.dbf’ SIZE 51200M;
 ALTER TABLESPACE TEMP_G3 TABLESPACE GROUP TEMP_G;
CREATE TEMPORARY TABLESPACE TEMP_G4 TEMPFILE ‘/u20/oradata/martd/temp_g4_01.dbf’ SIZE 51200M,
 ‘/u15/oradata/martd/temp_g4_02.dbf’ SIZE 51200M,
 ‘/u06/oradata/martd/temp_g4_03.dbf’ SIZE 51200M;
 ALTER TABLESPACE TEMP_G4 TABLESPACE GROUP TEMP_G;
Switch over database and user to new temp tablespace group—
 ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TEMP_G;
Break up original process from one process with complex aggregating to two CTAS, less one process sorting:
 SQL> create table orpt_test
 tablespace tbl_data1 compress nologging parallel 4
 as
 SELECT /*+ full(c) parallel (c 4) */ <–Note Parallel here, same requested parallel as # of temp
 c.m_id,

 PERCENT_RANK() OVER (ORDER BY c.orders_by_amt) pct_rnk
 FROM all_transactions c
 WHERE trans_type_cd != ‘F’;
 Table created.
 Elapsed: 02:56:46:22

Estimated time run was 16 hrs old way

SQL>CREATE INDEX orpt_tst_idx1
 on orpt_test(m_id, file_id) PARALLEL 4 nologging
 tablespace idx_data1;

Index created.
Elapsed: 01:42:15:43

Set table to unparallel and gather stats—
 ALTER TABLE orpt_test noparallel;
 exec dbms_stats.gather_table_stats( ownname=>’OWNER’,tabname=>’ORPT_TEST’, ESTIMATE_PERCENT=>.00001, METHOD_OPT=> ‘FOR ALL INDEXED COLUMNS’, GRANULARITY=>’ALL’,CASCADE=>TRUE, DEGREE=>4);

Create the secondary table that utilizes the index to ease into the hash and limit the temp usage on the amount of data it ends up having to perform in the sort if it was performed in one CTAS—

create table NEW_RPT_TBL
tablespace tbl_data2 compress nologging pctfree 0 parallel 4
 as
 SELECT /*+ parallel(o,4) */
 b_id,
 MIN(t_dt) this one,
 MAX(t_dt)that one,
 COUNT(*) ,
 SUM(o_amt) ,
 SUM(o_amt) this one,
 ….so on and so forth, more and more aggregation
 FROM
 (
 SELECT — /*+ parallel(c,4)  index(c,orpt_tst_idx1) use_hash(c cm mm m) */
 c.m_id,

 FROM orpt_test c , < Here’s our new table, already much of the aggregation performed!
 m_tbl1 mm,
 crm_mtbl2 cm,
 files_form3 m
 where c.m_id = mm.m_id
 AND mm.m_cd = cm.m_cd
 AND c.file_id = m.file_id (+)
 AND c.m_id = m.m_id (+)
 ) o
 GROUP BY m_id,
 c_cd,
 m_cd,
 l_name,
 f_id,
 b_id;

Table created.

Elapsed: 02:12:32:56

A quick observations of the work area verifies how the temp sorts are spread across the temp tablespaces that encompass the temp tablespace group to eliminate waiting as we write to one tempfile at a time:

SQL_TEXT SID TABLESPACE OPERATION_TYPE Temp MB
create table orpt_test tbl_data1

803

TEMP_G1 WINDOW (SORT)

10229

create table orpt_test tbl_data1

835

TEMP_G4 WINDOW (SORT)

13872

create table orpt_test tbl_data1

836

LOAD WRITE BUFFERS
create table orpt_test tbl_data1

847

TEMP_G1 WINDOW (SORT)

12974

create table orpt_test tbl_data1

803

LOAD WRITE BUFFERS
create table orpt_test tbl_data1

847

LOAD WRITE BUFFERS
create table orpt_test tbl_data1

835

LOAD WRITE BUFFERS
create table orpt_test tbl_data1

827

TEMP_G3 WINDOW (SORT)

11408

create table orpt_test tbl_data1

837

LOAD WRITE BUFFERS
create table orpt_test tbl_data1

837

TEMP_G4 WINDOW (SORT)

11535

create table orpt_test tbl_data1

827

LOAD WRITE BUFFERS
create table orpt_test tbl_data1

828

LOAD WRITE BUFFERS
create table orpt_test tbl_data1

828

TEMP_G3 WINDOW (SORT)

15940

create table orpt_test tbl_data1

853

LOAD WRITE BUFFERS
create table orpt_test tbl_data1

836

TEMP_G2 WINDOW (SORT)

10807

create table orpt_test tbl_data1

853

TEMP_G2 WINDOW (SORT)

18028

 

Drop “work” Table/Indexes post final table creation.
 DROP TABLE ORPT_TEST PURGE;

NEW PROCESS COMPLETE…

Was the goal met?
Largest amount of temp space used:  182GB,  (Old way: 721GB)
Time to complete process:  5hrs, 23 min., (Old way: 16 hrs)

Temp Tablespace Group Benefits to this entire tuning process:
Temp space usage without temp tablespace group, new process: 512GB, (over twice as much!)
Process completion time of new process without temp tablespace group: 11hrs, (5 hrs longer!)
Temp Tablespace Waits Eliminated with temp tablespace groups from original process:
Reads-  66%
Writes- 29%

Where are the improvements seen?
1.  I/O is distributed evenly across multiple datafiles instead of one datafile when presented with onle a single temp tablespace.

2.  Sorts in parallel performance increased, on average, over 20% for window and buffer sorts, (improvement was not seen for sorts involving rowid range scans…)
3.  Database overall improved as resources were re-allocated to all processes that may have been hindered by I/O bottleneck by heavy swapping to temp tablespace.

4.  For large hash processes, where temp tablespace usage is unavoidable, temp tablespace groups offer significant improvement in I/O performance and more CPU utilization.