High Water Mark
We are running a data conversion and got a wait event I don’t normally see: The brown is identified as Configuration. It I drill down, I can see more detail. Here light purple is HW Contention (i.e. High Watermark Contention). Darker purple is Write Complete waits, and yellow is buffer busy waits.
We have deferred segment creation switched on for the database. This means that the segment needs to be created before data can be written. The high watermark can only be moved by one process at a time.
It seemed obvious to me that all I need to do is allocate the extents, and
then everything will be faster. I
asked on the Oracle-l mailing list,
and Harel told me how.
I took a list of tables, and generated the SQL necessary to create the extents:
|
|
This creates a nice script to allocate extents:
|
|
And the same for the indexes
|
|
Meanwhile, Tim Gorman replied urging me to test and suggesting it might not be the panacea I was hoping for. As he said, it is pretty easy to create a table and put rows into it in parallel. I created some scripts. One to create a table: 01create.sql
A script to insert some rows into it: 02ins.sql
And a script to run them:
Now I have a reproducable test case. It would probably be better if I created a table with an index and a LOB and put some data in that, it wouldn’t be too difficult to do that, and I suspect these problems are worse for LOBs, or at least there are more segments which will need to be grown at the same time, especially at the start.
For the first test I ran the 01create script as follows:
I found I had to run 48 in parallel before I started to get significant HW Contention latch waits. The HW Contention waits I had in the conversion process were casused by running 53 in parallel, though that had more waits, presumably becuase those tables had indexes and some had lobs. However, I didn’t test for that because I just want to see whether allocating space helps. The next run was:
The next extent shouldn’t matter, as I hope I will be allocating as much as the table will need in the allocate extent command. Running it showed no significant difference in the HW Contention waits. This is rather disappointing.
Another test I did was to reuse the table from the last test, but delete the rows from it. This would preserve the high water mark. The 01create.sql script became:
This is the only thing I found that would make a difference.
I could have tried changing the tablespace, it currently uses Automatic Segment Space Management (ASSM), but I didn’t want to change the storage on the tables to support the conversion when it might not be as good for OLTP workloads.
It is slightly irritating for me not to have a solution to this (Just set X=Y and everything will be better!), but I have a better understanding from thinking about the situation, testing, reading, and asking on Oracle-l.
Here are things I have learned:
- When Oracle moves the high watermark on a table, only on session can do this at a time, so the HW Contention latch is used to single stream this.
- Blocks have to be formatted as part of this process. This seems to be a relatively expensive thing to do.
- There are ways to move the high water mark “down” to reduce the space taken by a table.
- There is no way to move the high water mark “up” to increase the space taken by a table, apart from inserting rows.
- You can allocate an extent using an alter table command.
- You can increase the next extent size on a table.
- Neither of these have any impact on the HW Contention waits.
- ASSM doesn’t give many ways of tuning underlying storage. Other storage options do, but that would involve changing the tablespace and a lot more testing.
- There is value in testing assumptions. It can be quite easy!
In addition to the discussion on the Oracle-l mailing list referred to above, I found this Ask TOM question about High watermark on a table and the article it refers to Resolving HW enqueue contention by Riyaj were also useful. There is a lot more to investigate here.