Top 60 Oracle Blogs

Recent comments

Oakies Blog Aggregator

Eleven Table Tennis: Basics

Assuming you are an IRL player who wants to get as close to the real thing as possible, that’s what I’d recommend:

Make sure you have enough space to play 147w, 295w, 768w, 1330w" sizes="(max-width: 1006px) 100vw, 1006px" />

The green box is your playing space. It should be a square of 2.50 m X 2.50 m ideally. Make sure to leave some space at the front, so you can reach balls close to the net and even a little across the net. Otherwise you may become a victim of ghost serves. Leave enough room at the sides – some opponents play angled, just like IRL.

If you don’t have enough space for this setup – maybe you shouldn’t play multiplayer mode then. You can still have fun, playing against the ballmachine or against the AI. Actually, I think it’s worth the money even in that case.

Use the discord channel

The Eleven TT community is on this discord channel:

I recommend you register there and use the same or a similar name as the name you have in the game. For example, I’m Uwe on discord and uwe. in the game (because the name uwe was already taken). This is handy to get advice from more experienced players, also the game developers are there. They are very responsive and keen to improve Eleven TT even more, according to your feedback.

There’s a preview version presently, that has improved tracking functionality. You can just ask the developers there to get you this preview version. I did, and I find it better than the regular version, especially for fast forehand strokes.

Setup your paddle

When you have the Sanlaki paddle adapter (as recommended in the previous post), go to the menu and then to Paddle Settings: 150w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" />

Click on Paddle Position and select the Sanlaki Adapter: 150w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" />

As an IRL player, you may start with an Advanced Paddle Surface: 150w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" />

Se how that works for you. Bounciness translates to the speed of your blade. An OFF ++ blade would be maximum bounciness. Spin is self-explaining. You have no tackiness attribute, though. Throw Coefficient translates to the sponge thickness. The higher that value, the thicker the sponge.


This takes some time to get used to. You need to press the trigger on the left controller to first “produce” a ball, then you throw it up and then release the trigger again to release the ball. Took me a while to practice that and still sometimes I fail to release the ball as smoothly as I would like to.

What I like very much: You have a built-in arbiter, who makes sure your serve is legal according to the ITTF rules. That is applied for matches in multiplayer mode as well as for matches in single player mode. But not in free hit mode! Check out the Serve Practice: 150w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" />

It tells you what went wrong in case: 150w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" />

Remove AI Spin Lock 150w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" />

I recommend you practice with the AI opponent in single player mode for a while. It has spin lock on per default, which means it will never produce any side spin. I find that unrealistic. After some practicing against the AI in single player mode, you’re ready for matches in multiplayer mode against other human opponents.

New Year … new idea … new channel

I’ve done a lot of presentations over the years, written a ton of blog posts, and over the past  5 years cranked out hundreds of tech videos of my YouTube channel.

But with the current state of the world, I also know that over the last year we’ve been awash with tech content that now comes exclusively over a virtual medium that generally requires us to stop our “day jobs” in order to focus on the content, whether it be a live presentation, recorded video or reading a long form blog post.

Many of us are simply too busy to dedicate that time to the plethora of tech content out there. (I love that there is so much great content, but lament the fact that we never have time to consume it!)

Then a lightbulb moment for me. Maybe the answer to allow people to get their tech content fix without needing to interrupt their daily work lives – and for that, a podcast seems a natural fit.

So I’m just trialling this at the moment, to see if this idea has legs.

Click below to get an introduction to the podcast, plus a couple of episodes. I’d love your feedback and thoughts either here as a comment or catch me on Twitter. If you’re not a fan, that’s cool, but if you like it, we’ll push ahead and make it official Smile

circle_largeThe Spoken Nerd podcast

Announcing SLOB 2.5.3

This is just a quick blog post to inform readers that SLOB 2.5.3 is now available at the following webpage: click here.

SLOB 2.5.3 is a bug fix release. One of the fixed bugs has to do with how SLOB sessions get connected to RAC instances. SLOB users can surely connect to the SCAN service but for more repeatable testing I advise SLOB 2.5.3 and SQL*Net services configured one per RAC node. This manner of connectivity establishes affinity between schemas and RAC nodes. For example, repeatability is improved if sessions performing SLOB Operations against, say, user7’s schema, it is beneficial to do so connected to the same RAC node as you iterate through your testing.

The following is cut and pasted from SLOB/misc/sql_net/README:

The tnsnames.ora in this directory offers an example of
service names that will allow the user to test RAC with
repeatable results. Connecting SLOB sessions to the round
robin SCAN listener will result in SLOB sessions connecting
to random RAC nodes. This is acceptable but not optimal and
can result in varying run results due to slight variations
in sessions per RAC node from one test to another.
As of SLOB 2.5.3, uses the SQLNET_SERVICE_BASE and
SQLNET_SERVICE_MAX slob.conf parameters to sequentially
affinity SLOB threads (Oracle sessions) to numbered service
names. For example:
With these assigned values, will connect the first
SLOB thread to rac1 then rac2 and so forth until rac8 after
which the connection rotor loops back to rac1. This manner
of RAC affinity testing requires either a single SLOB
schema (see SLOB Single Schema Model in the documentaion)
or 8 SLOB schemas to align properly with the value assigned
to SQLNET_SERVICE_MAX. The following command will connect
32 SLOB threads (Oracle sessions) to each RAC node in an
8-node RAC configuration given the tnsnames.ora example
file in this directory:
$ sh ./ -s 8 -t 32

Oracle 19c Automatic Indexing: Non-Equality Predicates Part II (Let’s Spend The Night Together)

In my previous post in this series, I discussed out Automatic Indexing currently does not consider Non-Equality predicates. Automatic Indexing will index columns based only on Equality predicates. So how does Oracle handle the scenario when an SQL has a mixture of both Equality and Non-Equality predicates? I’ll begin by creating two very similar tables, […]

VirtualBox 6.1.18

VirtualBox 6.1.18 has been released.

The downloads and changelog are in the usual places.

I’ve installed it on Windows 10, macOS Big Sur and Oracle Linux 7 hosts with no problems.

I’ll be running new Packer builds for the oraclebase/oracle-7 and oraclebase/oracle-8 vagrant boxes, so they should appear with the new version of the guest additions over the next day or so.




The post VirtualBox 6.1.18 first appeared on The ORACLE-BASE Blog.

VirtualBox 6.1.18 was first posted on January 20, 2021 at 3:50 pm.
©2012 "The ORACLE-BASE Blog". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement.

Hint Errors

This is a list of possible explanations of errors that you might see in the Hint Report section of an execution plan. It’s just a list of the strings extracted from a chunk of the 19.3 executable around the area where I found something I knew could be reported, so it may have some errors and omissions – but there are plenty of things there that might give you some idea why (in earlier versions of Oracle) you might have seen Oracle “ignoring” a hint:

internally generated hint is being cleared
hint conflicts with another in sibling query block
hint overridden by another in parent query block
conflicting optimizer mode hints
duplicate hint
all join methods are excluded by hints
index specified in the hint doesn't exist
index specified in hint cannot be parallelized
incorrect number of indexes for AND_EQUAL
partition view set up
FULL hint is same as INDEX_FFS for IOT
access path is not supported for IOT
hint on view cannot be pushed into view
hint is discarded during view merging
duplicate tables in multi-table hint
conditions failed for array vector read
same QB_NAME hints for different query blocks
specified number must be positive integer
specified number must be positive number
specified number must be >= 0 and <= 1
hint is only valid for serial SQL
hint is only valid for slave SQL
hint is only valid for dyn. samp. query
hint is only valid for update join ix qry
opt_estimate() without value list
opt_estimate() with conflicting values spec
hint overridden by NO_QUERY_TRANSFORMATION
hinted query block name is too long
hinted bitmap tree wasn't fully resolved
bitmap tree specified was invalid
Result cache feature is not enabled
Hint is valid only for select queries
Hint is not valid for this query block
Hint cannot be honored
Pred reorder hint has semantic error
WITH_PLSQL used in a nested query
ORDER_SUBQ with less than two subqueries
conflicting OPT_PARAM hints
conflicting optimizer_feature_enable hints
because of _optimizer_ignore_parallel_hints
conflicting JSON_LENGTH hints

CBO Example

A little case study based on an example just in on the Oracle-L list server. This was supplied with a complete, working, test case that was small enough to understand and explain very quickly.

The user created a table, and used calls to dbms_stats to fake some statistics into place. Here, with a little cosmetic editing, is the code they supplied.

set serveroutput off
set linesize 180
set pagesize 60
set trimspool on

drop table t1 purge;

create table t1 (id number(20), v varchar2(20 char));
create unique index pk_id on t1(id);
alter table t1 add (constraint pk_id primary key (id) using index pk_id enable validate);
exec dbms_stats.gather_table_stats(user, 't1');
        srec               dbms_stats.statrec;
        numvals            dbms_stats.numarray;
        charvals           dbms_stats.chararray;
                ownname => user, tabname => 't1', numrows => 45262481, numblks => 1938304, avgrlen => 206

        numvals := dbms_stats.numarray (1, 45262481);
        dbms_stats.prepare_column_values (srec, numvals);
        dbms_stats.set_column_stats (
                ownname => user, tabname => 't1', colname => 'id', 
                distcnt => 45262481, density => 1/45262481,
                nullcnt => 0, srec => srec, avgclen => 6

        charvals := dbms_stats.chararray ('', '');
        dbms_stats.prepare_column_values (srec, charvals);
                ownname => user, tabname => 't1', colname => 'v', 
                distcnt => 0,  density => 0, 
                nullcnt => 45262481, srec => srec, avgclen => 0
                ownname => user, indname =>'pk_id', numrows => 45607914, numlblks => 101513,
                numdist => 45607914, avglblk => 1, avgdblk => 1, clstfct => 33678879, indlevel => 2
variable n1 nvarchar2(32)
variable n2 number

        :n1 := 'D';
        :n2 := 50;

        /*+ gather_plan_statistics */ 
from    ( 
        select col0, col1
        from    t1 a
        where   a.v = :n1 
        and > 1
        order by 
        rownum <= :n2 
select * from table(dbms_xplan.display_cursor(null,null,'allstats last cost peeked_binds '));

From Oracle’s perspective the table has 45M rows, with a unique sequential key starting at 1 in the id column. The query looks like a pagination query, asking for 50 rows, ordered by id. But the in-line view asks for rows where id > 1 (which, initiall, means all of them) and applies a filter on the v column.

Of course we know that v is always null, so in theory the predicate a.v = :n1 is always going to return false (or null, but not true) – so the query will never return any data. However, if you read the code carefully you’ll notice that the bind variable v has been declared as an nvarchar2() not a varchar2().

Here’s the exection plan I got on an instance running 19.3 – and it’s very similar to the plan supplied by the OP:

| Id  | Operation                     | Name  | Starts | E-Rows | Cost (%CPU)| A-Rows |   A-Time   |
|   0 | SELECT STATEMENT              |       |      1 |        |  3747 (100)|      0 |00:00:00.01 |
|*  1 |  COUNT STOPKEY                |       |      1 |        |            |      0 |00:00:00.01 |
|   2 |   VIEW                        |       |      1 |     50 |  3747   (1)|      0 |00:00:00.01 |
|*  3 |    TABLE ACCESS BY INDEX ROWID| T1    |      1 |    452K|  3747   (1)|      0 |00:00:00.01 |
|*  4 |     INDEX RANGE SCAN          | PK_ID |      0 |   5000 |    14   (0)|      0 |00:00:00.01 |

Peeked Binds (identified by position):
   2 - :2 (NUMBER): 50

Predicate Information (identified by operation id):
   1 - filter(ROWNUM<=:N2)
   3 - filter(SYS_OP_C2C("A"."V")=:N1)
   4 - access("A"."ID">1)

The question we were asked was this: “Why does the optimizer estimate that it will return 5,000 entries from the index range scan at operation4?”

The answer is the result of combining two observations.

First: In the Predicate Information you can see that Oracle has applied a character-set conversion to the original predicate “a.v = :n1” to produce filter(SYS_OP_C2C(“A”.”V”)=:N1). The selectivity of “function of something = bind value” is one of those cases where Oracle uses one of its guesses, in this case 1%. Note that the E-rows estimate for operation 3 (table access) is 452K, which is 1% of the 45M rows in the table.

In real life if you had optimizer_dynamic_sampling set at level 3, or had added the hint /*+ dynamic_sampling(3) */ to the query, Oracle would sample some rows to avoid the need for guessing at this point.

Secondly: the optimizer has peeked the bind variable for the rownum predicate, so it is optimizing for 50 rows (basically doing the arithmetic of first_rows(50) optimisation). The optimizer “knows” that the filter predicate at the table will eliminate all but 1% of the rows acquired, and it “knows” that it has to do enough work to find 50 rows in total – so it can calculate that (statistically speaking) it has to walk through 5,000 (= 50 * 100) index entries to visit enough rows in the table to end up with 50 rows.

Next Steps (left as exercise)

Once you’ve got the answer to the question “Why is this number 5,000?”, you might go back and point out that the estimate for the table access was 95 times larger than the estimate for the number of rowids selected from the index and wonder how that could be possible. (Answer: that’s just one of the little defects in the code for first_rows(n).)

You might also wonder what would have happened in this model if the bind variable n1 had been declared as a varchar2() rather than an nvarchar2() – and that might have taken you on to ask yet another question about what the optimizer was playing at.

Once you’ve modelled something that is a little puzzle there’s always scope for pushing the model a little further and learning a little bit more before you file the model away for testing on the next version of Oracle.

Vagrant and Docker Builds: ORDS 20.4, SQLcl 20.4 and Database Patches 258w" sizes="(max-width: 196px) 85vw, 196px" />

The January Oracle quarterly patches were released yesterday, which prompted me to do some new builds.

We got Oracle REST Data Services (ORDS) 20.4 and SQLcl 20.4, which I use in a number of my Vagrant and Docker builds, so I updated them and ran some builds.

The Vagrant database builds, which include ORDS, can be found here.

The Docker ORDS builds can be found here. 295w, 57w" sizes="(max-width: 208px) 85vw, 208px" />

I also updated Tomcat to 9.0.41 and OpenJDK to 11.0.10_9 from AdoptOpenJDK.

Once I finished those I decided to try out the Oracle database 19c (19.10) OJVM+DB combo patch on a single instance build. That went fine. You can see that build here.

Since that went OK, I figured it was worth trying to update my OL8 19c RAC build with the 19.10 OJVM+GI combo patch. That also went fine. You can see that build there.

I wasn’t really expecting to cover so much ground so quickly, but that’s the great thing about automation. </p />

    	  	<div class=

Sourdough – Making a Loaf

<<– Creating the Sourdough Starter

Anyone who follows me on Twitter knows I like making sourdough bread. For me, a sourdough loaf is a real treat. I love the combination of a thick, crunchy crust and the soft, strong-flavoured inside. I’ve been asked a few times how I make my bread and I keep saying I will write it up. This blog post is the fulfilment of that promise.

Making sourdough is a longer, more complex baking process than most modern versions of baking bread, but it is actually a very old method of baking and was probably the main method used by the peasant and working classes over the last few hundred years. It takes several hours to make sourdough. I start mine in the evening and bake it in the morning.

Work is stressful (even working in I.T. from home), this pandemic is stressful, baking a nice loaf of bread helps balance that stress.

A key part of the process is that you need a “starter”, a mixture of flour, water, and actively growing yeast. I did a long and detailed post on creating a starter about a month or so ago. If you created a starter then and have been feeding it since, it’s well past time to make a loaf!

Get the Starter Active

If the starter mixture is in the fridge, take it out of the fridge several hours before you are going to use it. If I am making my dough in the evening (my usual method so it can prove overnight) I take the starter out the fridge about noon.

A few hours before you are going to make your dough (usually 6 hours or so for me), mix up 200 grams of strong, white bread flour with tepid water so it is a similar consistency to porridge, add it to the starter and give it a good stir.

This should help get the starter really active and, after a couple of hours, you should see bubbles in the mixture and the volume will increase. I do not seal the jar during this process, I leave it with the lid over the top of the jar but not clipped or screwed down.

Making the Initial Dough

I’ll give you two recipes for making the dough. The first is from a man called Paul Hollywood, who is a very well known and successful baker in the UK. He is one of the judges on “The Great British Bake off“, which is one of the most popular TV programs in the UK. I know the program has been syndicated across the globe, with over 25 countries showing their own version, and a couple showing the UK original. The second recipe is mine, which is derived from Paul Hollywood’s. I increased the size of the loaf as I wanted something to provide sandwiches for 2 people for 2 days and I found a little more salt and a lower percentage of starter gave results I preferred. Less starter seems to give a better final rise to the loaf. Please note – Paul Hollywood is a considerably better baker than I! Perhaps try his recipe first.

Paul Hollywood recipe

  • 375g Strong white bread flour
  • 250g sourdough starter
  • 7g salt
  • 130-175 ml tepid water
  • a teaspoon of olive oil

Martin Widlake recipe

  • 500g strong white bread flour
  • 200g sourdough starter
  • 10g salt (but no more!)
  • 7g sugar
  • 200-220ml tepid water
  • a teaspoon of olive oil



The below is based on my recipe

I have a little plastic jug for measuring the water. Before I put any water in it I put the 10 grams of normal, fine table salt (1). Do not go above 10g of salt in 700g total flour & starter as too much salt inhibits the rise of the loaf. I’m adding about as much salt as you can without this happening.  I also add a teaspoon of sugar (7 grams) as I feel it balances the sour of the loaf and slightly boosts the loaf flavour. Skip this if you like. 406w, 129w, 258w" sizes="(max-width: 204px) 100vw, 204px" />

I then put 500 grams of strong bread flour into the mixer bowl (see later for some variations to 500g of flour). As I add the flour I also dribble in the salt/sugar mix. This is to help it all mix in evenly. I found that if I just chucked the salt in after all the flour, again the rise could be problematic and the bread seemed to be a bit patchy in it’s flavour. Give the flour with the salt/sugar in a quick swirl with a spoon or something. 522w, 130w" sizes="(max-width: 261px) 100vw, 261px" />

I now add 200 grams of sourdough mixture and about 100ml of the tepid water. I do not add it all as I use a food mixer to initially combine my dough. We have a Kenwood Chef that is 40+ years old. To make bread dough in a food mixer you need a dough hook. The one you see in the picture by the recipes is only a few years old, it is coated with Teflon to help the dough to not stick to it.

The mixer can throw little fountains of dry ingredients out of the bowl so I put a towe over the whole thing. If you do this, make absolutely sure the towel is not going to get caught on the dough hook/mixer! With the mixer on it’s lowest setting, I slowly add more of the water to each side of the bowl so that the ingredients combine. I have found that as the dough mixture gets towards the consistency I want, or is damper than I am aiming for, it wraps around the dough hook and no longer mixes! It just wizzes around with the hook.  This is why I added the water slowly and keep about 20-30ml in reserve. Then, when all the ingredients are well mixed but it is not quite forming a single ball, I add the last of the water and keep the mixer running until the dough does wrap around the hook and stay on it. Take it off the hook and make it into a rough ball, as shown In the picture of the mixer.

You can mix it all by hand, which is fun, but your hands get really messy and it takes longer. If you do mix it all by hand, add the water bit by bit until the dough is quite sticky.

I now put a little olive oil, half a teaspoon is all, on a thoroughly cleaned work surface and spread it around  into a 20-30cm circle. I drop the dough in the centre of this and I knead it by hand to finish it off and get a smooth consistency in the dough. Different people like to mix their dough in different ways. I push into it with the heel of my hand, stretching it against the work surface, and then fold it over a little and push into it again. I do this with just the one hand in a regular rhythm of about one one push a second, slowly rotating the dough ball and moving it around so I am working all of the ball. I swap hands occasionally for a full upper-body workout…

Other people slap the dough onto the work surface or throw it down, others squidge it out with both hands and then fold-and-squidge. Do what seems right to you. There are lots of videos on the internet.

The whole aim is to get all the ingredients mixed in smoothly and keep going until the dough is a little elastic. Apparently the best test as to whether you have worked the dough enough is that you can stretch some thin with your fingers and see light coming through it. I don’t do this, it does not seem to work well with my dough, maybe as I do not add enough liquid, maybe because sourdough is a little different. I know it is ready as it…. feels ready. Smooth, not rubbery, but with some stretch to it. Because I use a machine to initially mix and knead the dough I only have to hand knead it for 5 minutes. If you mix the dough by hand then you will need to knead it for 10, 15 minutes. Maybe more.

The whole idea of the kneading is to get some of the protein in the mix, the gluten, to form long chains which give the final loaf it’s structure of a soft and flexible material. If you over knead the dough then the bread will not rise so well and the bread will be rubbery and dense. You don’t want rubbery, dense bread.

Proving the Dough

Once your bread is kneaded to the consistency you want, you have to let it prove – which means left alone to grow. You prove the dough twice.

Use the other half a teaspoon of oil to lightly oil the inside of the mixing bowl. The only reason for the oil is to stop the dough sticking. Put the dough ball into the bowl and cover with clingfilm or similar. I use a clear, plastic shower cap that I can re-use dozens of times as (a) it’s so easy to pop it over the bowl and (b) less plastic waste. 444w, 138w, 275w" sizes="(max-width: 223px) 100vw, 223px" /> 600w, 150w" sizes="(max-width: 300px) 100vw, 300px" />

You need to keep the dough at about room temperature – between 18C and 22C – for several hours. Less time if it is warmer, more time if it is cooler. I make my dough about 8-10pm in the evening and leave it overnight, near a radiator that will come on in the morning. This seems to work for my dough.

During the proving stage the yeast in the dough consumes sugars (the sugars come from the starch in the flour being broken down) and they produce carbon dioxide (CO2). this is what makes the dough grow and become soft.

In this first prove of the dough it should doubled to tripled in volume, and become soft and spongey to a light touch. Sticking a finger in it will leave a dent that only partly fills in.

Lightly dust a clean, dry area on your work surface with plain or bread flour and turn the dough out of the bowl it has proved in onto the area. I lightly dust one side of the bowl to stop the dough sticking to it and I ease the dough from the sides and bottom of the bowl with a small, flexible spatula – one of those made of silicon or soft, heat resistant plastic. In the picture above of the dough on the work surface you can see bubbles in it – this is from the CO2.


You now need to “knock back” the dough – knead  it all over with your knuckles or, like I do, give it 30 seconds of kneading like you did when you first made the dough. Some instructions tell you to do things like make a ball after knocking it back and  tuck the dough down under the ball and into the bottom of it. I think these are to create little air pockets in the dough that make the large voids you get in posh hippster café sourdough. I don’t want those large voids. I keep the flour dusting to a minimum and push the dough together well to avoid any air gaps or having any folds in the dough which do not “heal” (stick to each other).

You now need to let the dough prove for a second time. I use a “banneton” for this, a special wicker or similar material bowl that is specifically for the final proving of bread. They also impart a nice pattern on the loaf. Dust whatever bowl or banneton you are using well, put the dough into it and push it down firmly. Lightly dust the top and then cover a plastic bag or similar. You want the bag to be above the dough so when it rises it does not contact the bag, as it will stick to it.  I put the showercap I used earlier back over it, with the damp side inwards to stop the top of the bread drying out too much. Put somewhere warm and leave for two hours. If the house is not that warm, I put the oven on and set it to 50C, then turn it off and pop the loaf in that. If you are dead posh you might find your oven has a proving oven compartment or a plate warmer you can use.

After a couple of hours the dough should have risen a little again and have a smooth top. It is now ready to bake

Baking the Bread.

A key to getting a good bake where the bread rises evenly and you get a good, strong crust is moisture. You need the atmosphere around the loaf to be damp for the first 20 minutes or so of baking.

I’ve achieved this with two methods – baking in the oven with a tray of water, and using a Dutch Oven.

In the Oven With a Tray of Water.

Pre-heat the oven to 220C and put a shallow tray on the lower shelf.

Heavily dust a baking tray with flour, or flour and semolina (semolina is better at preventing the loaf from sticking, but I find flour on it’s own works just fine and I stopped using the semolina as I’m lazy). Carefully tip the loaf out on the tray and slash the top several times. I have a special, small, gentle serrated knife just for this, it seems to work better than a smooth blade. He’s called Mr Slashy the knife. This scouring allows the crust to expand more easily during the cooking.


Dust lightly with flour and immediately put the loaf into the oven, and put about 500ml of warm water in the shallow tray. This will create steam as the bread cooks.

Cook at 220C for 30 minutes and then turn the oven down to 200C and cook for a further 15-20 minutes. The bread should have risen and turned a lovely golden brown. You can test if it is done by tapping the bottom of the loaf, it should sound hollow. If, like me, you like your bread slightly darker with a stronger crust, extend the higher temperature period from 30 minutes to 35, 40 minutes.

Take the loaf out and move it onto a wire rack to cool.

In the example I show, the loaf is a weird shape. I think this is because, with this loaf, I forgot to put the water in the oven with the loaf, then added cold water to the tray, not warm. As a result there was not enough moisture, the crust formed early and the still-expanding loaf could no longer grow and burst out the side of the crust. If this happens to a lot of your loaves, try scoring more or gently wetting the top and sides of the loaf before the final dust of flour.

It tasted just fine!

In a Dutch Oven. 474w, 150w, 300w" sizes="(max-width: 237px) 100vw, 237px" />

A Dutch oven is basically a heavy iron or aluminium casserole with a well fitting lid. You bake the bread with the lid on initially to trap moisture. I use an iron casserole dish about 26cm in diameter. The casserole needs to be about 5cm wider than your uncooked loaf, to allow for expansion. If you already have a casserole dish you might need to change your loaf size or the bowl/banneton you prove it in so that the loaf fits!

Pre-heat the oven and the casserole dish to 230C. Yes, 230C. It take about 15 minutes for my casserole to heat up fully.

Take out the casserole and  heavily dust the bottom with flour. You will know it is warm enough as the flour will smoke gently.

As carefully as you can, turn out the loaf into the casserole dish. I turn the banneton upside down and hold the loaf in place with my fingers, shake it slightly until the loaf drops onto my fingers and then I open my fingers to let it drop the 6 inches into the casserole. Do not let your skin touch the casserole dish, it hurts like hell! Slash the top of the loaf several times, again keeping the fingers away from the hot metal.

This is the main disadvantage of using a casserole, getting the loaf in and slashing the top is harder and the danger of a nasty burn is ever-present. I have tried turning the loaf out, slashing it and then transferring it to the casserole, but it knocked a fair bit of air out the loaf and reduced the rise.

Cook at 230C for 20 minutes. Remove the lid (the loaf will still be a cream colour) and cook for a further 15-20 mins. Turn the oven down to 160 and cook for a further 15-20 mins. You turn the temperature down more with the casserole as it retains heat for a while.

You might notice my oven says 235 and 165C. My oven temperature is a little cool (I tested with an oven thermometer) so I added 5C. You do get to know your oven when you do baking!






You loaf should now be dark golden brown. Remove the casserole from the oven. I put a little fan blowing air over the casserole for 5 minutes before I extract the loaf. Using a cloth to protect your fingers, take out the loaf and leave to cool on an a wire rack.

I swapped to the Dutch Oven method as a couple of friends recommended it and the flush of steam from the “oven with a tray” method was making the control panel of my oven go funny. I’ve already had it repaired once.

Having swapped, I think overall the Dutch Oven method gives a better loaf. I have far fewer issues with the loaf rise being uneven and part of the load bursting out the side or the crust “tearing” at the sides.

If I decide to make larger loaves I’ll simply swap to the oven-and-a-tray-of-water method.





Once the loaf is out the oven I tend to start losing control of my salivary glands and I am desperate to eat it, so I use a little fan to help it cool in about 1/2 an hour. If you have more will power than I then it takes an hour or so for the loaf to cool naturally.

I love to cut open the loaf and eat it when it is still a little warm. The one disadvantage of this is that the loaf will lose extra moisture as a result of this, so any bread you save until tomorrow will be a little drier. I hardly ever manage to hold off cutting it early for the sake of a better experience tomorrow! 498w, 150w, 300w" sizes="(max-width: 249px) 100vw, 249px" /> 480w, 150w, 300w" sizes="(max-width: 240px) 100vw, 240px" /> 420w, 150w, 300w" sizes="(max-width: 210px) 100vw, 210px" />

Alterations to the recipe

I sometimes replace 150-200 grams of the white bread flour with spelt or mixed seed flour. It does seem to drop the rise a little though. I have tried adding a little dried bakers yeast to balance this but with limited success.

I have replaced all 500 grams of white bread flour with brown bread flour. It was OK, but despite me generally preferring brown bread,  with sourdough it just does not seem right to me.

I really like adding a teaspoon of smoked, sweet paprika to the mix. This is partly why I put the salt etc in the jug I later user for the water, I put the extra flavour in the jug too and the water washes out any flavouring that has remained in the jug.

Chop up a handful of sundried tomatoes (drained of their oil on kitchen paper as the oil seems to inhibit the rise) and add those with a good squirt (say 25ml) of double strength tomato puree.


1) You could use sea salt or Pink Himalayan salt instead of dirt-cheap table salt –  but it’s all the same stuff really, it’s dried out sea and mostly consists of the specific salt compound sodium chloride. The stuff dug out the ground is from a few hundred million years ago and sea salt is usually from drying out current sea water. The problem with salt that is not table salt is it is probably not as fine so it might impede rise more.


APEX Application Development Service on Oracle Cloud 211w" sizes="(max-width: 162px) 85vw, 162px" />

A few days ago Oracle announced the APEX Application Development Service on Oracle Cloud.

I had a sneak peak of this service last October. I’ve used APEX since it was know as Project Marvel, but despite this I’m renowned as the worst APEX developer on the planet. I think I was invited as a control subject… </p />

    	  	<div class=