Skip to content

Oracle query only runs consistently when adding a random comment

Edit: Solved! thanks to @kfinity.

AskTom suggests using select /*+ opt_param(‘_optimizer_use_feedback’ ‘false’) */ at the start of your query to disable the feedback usage. This has fixed the problem for me.

tldr: Adding a randomized comment to a query makes it run consistent, removing this comment breaks it.

Warning: long.

Environment

My preferred way of working is with queries in the source as string so that they are in version control and I can see changes over time. Along with that I use dapper and the oracle.ManagedDataAccess NuGet package. The application in question is a WPF app (in both cases) running on .NET framework 4.7.2. I’m using Visual studio professional 2017 15.9.5.

The problem

About a year back I encountered this problem with a query. I don’t remember which it was, I do know that I didn’t have the time to document it and post it here. I do now and I ran into the same problem. Back then I somehow figured out that if I restarted my PC or changed the query text, it would run fine again. Just occasionally the symptoms of the problem would show up, I’d add a comment to the query, or remove the one previously there, I would test that specific function every release. I’d test it everytime because if it was faulty on my machine, it would also be faulty on the target user machine. At the time I figured it was a driver/hardware issue with my pc. The way I figured out I could fix it by changing the query text is because I would cut and paste (ctrl-x ctrl-v) the entire query from the code to Oracle developer and edit it there. At some point I noticed even an extra whitespace or enter would make it work again.

Back to now, I’ve got the problem again. This time it’s different because it doesn’t fail occasionally anymore. It’s very consistent. Thinking back about how I figured this was a driver/hardware issue, I build and ran the application on 3 different machines, all the same results. I can run the query in Oracle developer, using ctrl + end to run the entire query, not just 50 lines. It runs in about 10 seconds. It runs consistently, over and over again, which makes sense if nothing changes.

If I run it from my application, it runs fine – but only once. It takes about 10 seconds as well. If I refresh the data, which runs the query again, it hangs. There are no exceptions, if I break the debugger it’s just chilling on the database.Query<>() call. If I either restart my PC or change the query, it will run – exactly once.

v$session_longops/full table scan

Of course, I went to google for help. Found some interesting articles that didn’t really help me along:

https://mjsoracleblog.wordpress.com/2014/10/24/oracle-performance-mystery-wildly-varying-query-response-time/

Oracle inconsistent performance behaviour of query

Until I found this:

https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1191435335912

They mention v$session_longops which supposedly gives us insight into long running operations.

I ran this while I had just refreshed the data in the application, causing the query to run for a second time. I see this:

query results

The first query ran fine, indexes where fine. The 2nd time it started up a full table scan. It doesn’t need this because it runs fine in the first time and in oracle developer as well. As expected, if I leave it running (takes over 20 minutes) the table scan completes and I get the same result as the first time around.

I found that you can use explain plan for to explain a query plan without using the GUI in Oracle developer. This gave me 2 wildly different plans, the one in Oracle developer always has this note: - 'PLAN_TABLE' is old version. So I’m not sure that I can trust this information, I don’t know what to do with it.

Plan from Oracle developer

Plan from code

The fix

Like I said before, adding or removing a comment or rather changing the query text fixes the problem and doesn’t start a full table scan, ever. I added a comment containing DateTime.Now to the query so that it is always different. It consistently works. While technically this fixes the problem I think it is quite a ridiculous fix to an even more ridiculous problem. I’d rather know why this happens and if maybe I’m doing something else wrong. So the question is, why does a randomized comment fix my query?

The code

Some context: this is an ERP system, the query gets all the workorders that have a hierarchic structure, or that are just on themselves, combines them, then adds their required materials and some other information like their description. It only does this for workorders that are not closed yet.

SQL:

C# (does NOT work):

C# (does work consistently):

Advertisement

Answer

I’m not sure this is really an answer, but it’s too long for a comment.

I think a fast first query followed by a slow second query often indicates a statistics/cardinality feedback issue.

Basically while running the query the first time, the optimizer might detect that the estimated cardinality (number of rows) from the current table/index statistics are pretty inaccurate, so it tries to cache more accurate stats for the next run of the same query. But sometimes that actually makes things much worse.

As a quick fix, AskTom suggests that you can try disabling that feature with the /*+ opt_param('_optimizer_use_feedback' 'false') */ hint, or use SQL Plan Management to save the good plan, as Ted mentioned above.

In the longer term, I think it might indicate that some of your statistics might be stale? You can narrow down the problem stats by doing cardinality tuning and looking for where in the plan the actual rows are a lot higher than the expected rows. The basic process is to run your query with the /*+ GATHER_PLAN_STATISTICS */ hint and then do SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'ALLSTATS LAST')); to see the results.

User contributions licensed under: CC BY-SA
7 People found this is helpful