Oracle going seriously wrong on a "simple" sql statement

Posted on 2006-11-07
Last Modified: 2010-07-27
Take a look at this statement:

INSERT INTO SAVEDLISTWIDGET(SAVEDLISTID, WIDGETID) SELECT 2 AS SAVEDLISTID,A.WIDGETID FROM  WIDGET A  WHERE (A.LOCATIONID IN (2,3,623,22,595,578,579,628,589,580,581,582,590,23,583,834,594,34,35,36,37,479,38,39,40,41,42,43,44,521,45,512,46,47,501,48,49,50,51,52,53,54,55,56,57,482,504,508,520,59,60,61,62,63,64,499,500,66,67,68,69,481,667,668,626,532,4,596,74,75,77,78,79,489,517,80,584,490,81,476,82,83,84,85,86,87,480,88,89,506,90,477,91,92,93,94,485,95,491,669,6,7,96,492,670,671,672,97,98,99,100,519,101,102,103,104,593,106,107,673,674,675,478,514,510,507,676,677,678,679,680,681,682,683,684,685,686,687,108,688,689,591,585,586,109,110,523,111,511,112,487,113,114,649,115,116,117,118,119,120,121,122,123,124,518,125,126,691,127,692,693,694,695,128,70,696,697,698,130,483,488,831,505,625,587,513,131,522,132,699,700,701,133,134,524,135,136,137,138,139,503,140,141,142,143,144,145,146,502,147,703,148,704,705,706,707,708,709,710,711,712,713,714,715,716,717,149,150,151,152,486,718,153,154,155,156,157,158,159,719,588,160,161,48
,180,786,787,554,309,310,311,312,788,313,314,448,315,789,790,316,555,317,318,449,319,320,321,791,792,793,556,557,322,794,323,324,450,14,525,622,643,795,796,330,331,332,333,335,336,797,798,799,535,801,802,803,804,805,806,807,808,800,529,809,810,811,812,813,814,815,816,536,817,818,819,820,821,822,823,824,825,560,826,827,828,569,568,566,577,420,461,570,567,18,19,644,611,364,365,366,367,368,462,369,370,371,612,463,372,373,374,375,376,377,378,613,379,380,381,382,383,384,385,386,387,388,389,390,464,391,392,393,465,394,395,396,397,398,399,400,401,614,466,402,403,404,467,615,405,406,616,407,408,409,410,411,412,617,413,414,415,530,20,618,337,338,339,340,341,342,343,468,344,345,346,347,472,624,469,470,473,474,475,471,21,645,597,598,599,600,601,602,603,604,605,606,607,608,609,610,619) AND A.CATEGORYID IN (9,59,66,47,52,68,61,56,49,50,71,51,67,76,64,70,55,58,63,75,62,72,65,57)) AND A.BUDGETID = 1

After about 12 minutes this thing raises

ORA-03113: end-of-file on communication channel - OraOLEDB

SavedListWidget contains 8844 rows, and is Pkeyed on SavedListID,WidgetID
Widget contains 2187 rows
Location contains 715 rows
Category contains 55 rows

Database is fully normalised with LocationID and CategoryID indexed and the FK/PK relationships in place

There's no locking issues, I restarted the Oracle box and ran it from a simple vb program (.net and vb6 drivers give same error).

On smaller volumes of LocationIDs the statement works fine.

Oracle version is 9.2. Note some numbers might've got split in the paste, but it is syntactically correct. This is the cause of my earlier and still open thread:

Please let me know if you have any ideas on this, and whether any settings can be put in place to fix it without changing the sql.

Question by:plq
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
  • 2
  • +2
LVL 143

Assisted Solution

by:Guy Hengel [angelIII / a3]
Guy Hengel [angelIII / a3] earned 300 total points
ID: 17892888
well, this looks like a rather insane number of values for a IN() clause, additionally I see there are alot of ranges.
could that not be implemented a bit differently?

a first try would be to replace the
WHERE FIELD IN ( val1, val2, val3 ... )
WHERE FIELD IN ( select val1 from dual union select val2 from dual union select val3 from dual ... )

this would make the query longer, but the difference would be to change the enumerated list in a table of values.


Author Comment

ID: 17892972
I will try that. Thanks

But I'm also really interested in whether we can get this sql statement working as it is, by changing settings, oledb parameters, etc.

We can change oracle settings but the sql is coded into an enterprise product and to rebuild, retest, redeploy the product would be a lot of work and expense.

And if I may just say this..., if the statement was outside of oracles capabilities it should tell you that before it sits there grinding for 12 minutes and then kills the connection ? !! OK I've worked on oracle for a while too.

LVL 35

Assisted Solution

by:Mark Geerlings
Mark Geerlings earned 200 total points
ID: 17893549
This statement is "simple" in one way, but that huge list of "in" values is not a good way to get the job done in Oracle.  I agree that Oracle should either accept the statement and process it promptly, or return an error that could be handled.  The ORA-03113 is about the worst one to get, since that one cannot be handled in an Oracle program.

I realize this may not be easy, but the best solution to this problem (at least with Oracle) is to avoid constructing huge "in" lists like this.  One option would be to create another table that contains LOCATIONID and one or more "flag" or date columns, especially if this list is fairly static.  Then you set up a mechanism to update those records and use a sub-query here something like this:

FROM  WIDGET A, new_table b
and b.[some_column] = [some_criteria]
AND A.CATEGORYID IN (9,59,66,47,52,68,61,56,49,50,71,51,67,76,64,70,55,58,63,75,62,72,65,57)) AND A.BUDGETID = 1

You may want the same technique for CATEGORYID also, if that list can grow large.

If this large "in" list is not at all static, you could still use a sub-query in your insert.  Just create a global temporary table for the LOCATIONID values, and insert each of them into the global temporary table first, then base the sub-query on a select from the global temporary table.
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

LVL 18

Expert Comment

by:Jinesh Kamdar
ID: 17894079
Try changing the order of the conditions in ur WHERE clause i.e.

WHERE A.BudgetID = 1
AND A.CategoryID IN (9,59,66,47,52,68,61,56,49,50,71,51,67,76,64,70,55,58,63,75,62,72,65,57))
AND A.LocationID IN (....................................................................................................................................................................................................................................................................................................................................................)

An alternative as angelIII suggested would be to specify the range of values between the min & max and then exclude those not in the range since that would be a much smaller list i suppose i.e.

WHERE A.BudgetID = 1
AND A.CategoryID IN (9,59,66,47,52,68,61,56,49,50,71,51,67,76,64,70,55,58,63,75,62,72,65,57))
AND A.LocationID BETWEEN 2 AND 900
AND A.LocationID NOT IN (..........................................)

Expert Comment

ID: 17895554

correct the line below... there is comma missing.. or you must remove space.


also remove the '(' before A.LocationID
use where cond. in the following manner.. no need to change sequece of cond.
where A.locationID in (1,2,3,..)
 and A.SomeOtherID in (6,7,8...)
 and A.SomeOtherCond = 'test'

Author Comment

ID: 17896218
Thanks for all the feedback. The missing comma was just a paste issue as commented earlier.

I am running a series of tests this morning to get to understand whats going on a bit better. I'm going to cut this back to find the "minimum scenario" where the problem occurs, and will report back here.

My initial tests show that

- Remove the category clause and it runs sub-second
- Remove the location clause and it runs sub-second
LVL 143

Accepted Solution

Guy Hengel [angelIII / a3] earned 300 total points
ID: 17896228
I guess you have 2 indexes, 1 on Category field, and 1 on location field.

could you change one of the 2 to add the other field to it?
I suggest to change the index on the Category field to add the location field as second indexed field...

Author Comment

ID: 17896593
I forgot to mention, but its probably obvious, that the INSERT statement is not relevant, and the problem is reproduced in just the select statement.

AngelIII - I firstly tried an additional index for CategoryID, LocationID. That didnt help.  Also I tried a covering index on WidgetID,CategoryID,LocationID,BudgetID. Still didnt help

I have done several experiments with changing the sql around. The order of where conditions is not relevant. Adding extra where clauses on location doesnt make any difference.

So then I went to the oracle server, login as sys/sysdba, and change the following:

Setting        Old Value        New Value
Shared Pool    48                    96
Buffer Cache   24                    48
Large Pool       8                     80

And the problem went away. consistently

So I put the oracle server back to its original settings.........and the problem is still gone away

Several expletives and profanities parted my lips at this stage, and Larry Ellisons parentage was brought into question.

Now I reboot the oracle server, start the db, and try again. Its STILL working. Original settings are still showing too.

Any ideas what could have chaned ?

I'm going to try this on the customers live server where the problem is happening.....


Author Comment

ID: 17897035
Hmmm customers server has Shared Pool 184, Buffer Cache 560. Their PGA target was 245 MB (my server was 24MB)

So I try increasing Large Pool to 80 MB, and cut the others back..

Problem still happening. So now increase everything.

One thing I did do on our server which I didnt mention above was "compute statistics" on the widget table.



So... did compute statistics on the widget table, and now its working at the customer server too.

Points coming up...
LVL 35

Expert Comment

by:Mark Geerlings
ID: 17897586
I'm glad that the problem seems to be solved, or has at least quit happening.  Your init settings (for: shared_pool, buffer_cache and large_pool) look unusually small.  The values from your customer's server look more typical.

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction A previously published article on Experts Exchange ("Joins in Oracle", makes a statement about "Oracle proprietary" joins and mixes the join syntax with gen…
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
This video shows how to set up a shell script to accept a positional parameter when called, pass that to a SQL script, accept the output from the statement back and then manipulate it in the Shell.
Via a live example, show how to restore a database from backup after a simulated disk failure using RMAN.

695 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question