Thanks for your answer, it brought me closer to my goal. We don‘t need the order by to be deterministic, but consistent within the query. Thus the interesting part for me is not between different queries run separately, but within the very same query.
Lets take three tables A,B,C and look at one row A1, which happens to match two rows B1 and B2 by some join condition. C shall be the table that matches different rows C1-Cn to A1, but we take one of them by choosing the first row from this non-deterministic order by.
Ignore other possible join orders, just look at two: If the optimizer chooses to join A->C->B, it will match A1 with any single Cx, can’t say which, but only one. Next step join with B and you get the results: A1-Cx-B1 and A1-Cx-B2.
But if the optimizer chooses to join A->B->C, it will get A1-B1 and A1-B2. If it then uses Hash-Join for C it will read any Cy once and get a similar result as above.
But if it opts for the NL, then there will be two reads of C, one for A1-B1 and one for A1-B2. And here comes my question: Do we possibly end up with a result set like A1-B1-Cx and A1-B2-Cy, where Cx and Cy is different? And if yes, how can I produce this result?
Our real life query is a single sql - much more complex though - and in production does very seldomly and not reproducibly deliver such Cx and Cy results. But until I can reproduce this behavior, it could be some other part of the complex query, that causes the problem.
https://livesql.oracle.com/apex/livesql/s/m9lxl8otep99ama1ggavsimzn In my test script A would be rau_company, B would be a bit more complex with rau_owner & rau_companyowner and have more matching rows and C would be rau_address.
Your idea with adding clustering worked well to change the order by on my table, but only once. Even after I dropped the table and recreated it without clustering my local 12.2 kept the new order. I tried LiveSql and there the clustering order did not stay after drop/create. But with LiveSql I do not know how to get two different sessions, where I could run my 30-sec query and “alter table” in parallel.
Your idea with the index worked better. If you create it with asc or desc on street the first row of the order by will flip consistently (Statement 1 & 4 of below liveSQL). Thus I was positive that my query (Statement 29 in above liveSQL) which would use NL to iterate over the order by and that runs about 30 seconds would reflect the flip, if I recreated the index in the other direction while the query is running. But that was not the case, at least not in my local 12.2. The query returned only one row reflecting the order that was present when the query was started. Thus there must be some feature that keeps the result consistent, even though the order by in the parallel session already returns the other result, or have I made some other error?
https://livesql.oracle.com/apex/livesql/s/m9s6g03i3d0lp4g3aawhynjyj (liveSQL with drop/create of the index)
March 29, 2022 - 6:41 pm UTC
We don‘t need the order by to be deterministic, but consistent within the query.
If you have a non-deterministic sort, all bets are off. While you often get lucky and still get the same output, you might not.
Thus there must be some feature that keeps the result consistent
The result of a query is fixed at the time it starts.
Think about this:
You query one table which does a full table scan with no sorting. While this is running, you re-org the table in a way that changes the physical order of the data. If the query picked up this change immediately, potentially you'd read some rows twice and skip over others.
This would be bad.
So Oracle Database uses undo to reconstruct the table state at the time the query started to ensure you get consistent results.