{"id":1691,"date":"2012-10-14T12:00:00","date_gmt":"2012-10-14T12:00:00","guid":{"rendered":"http:\/\/orcldoug.com\/blog\/?p=1691"},"modified":"2012-10-14T12:00:00","modified_gmt":"2012-10-14T12:00:00","slug":"parallel-dml-and-odp-net","status":"publish","type":"post","link":"http:\/\/orcldoug.com\/blog\/2012\/10\/14\/parallel-dml-and-odp-net\/","title":{"rendered":"Parallel DML and ODP.Net"},"content":{"rendered":"<p>\nI&#8217;ve been doing a lot of work around large volume data loads into an Oracle 11.2 database recently using External Tables and Parallelism and, despite the fact it&#8217;s all used well-known techniques, I think it&#8217;s probably worth a couple of posts to re-emphasise how successful using the right tools for the right job can be. <\/p>\n<p>But first, we ran into a particular problem that threw us off-track for a few hours and this post covers that issue. I have a feeling that at least one person one day will land at this post via Google or from a vague memory of me writing about it and the hassle it saves them will make me smile!<\/p>\n<p>Our application is written using a combination of C# and PL\/SQL so, even as we&#8217;ve been implementing more functionality in the database, we still depend on scheduling software calling C# that in turn calls PL\/SQL. As I was developing the data loading code, I simplified testing for myself by knocking together a basic .sql script that called the various PL\/SQL procedures in the correct order. Everything looked great so I checked in my code and gave the appropriate call specifications to the C# developers to write wrapper procedures. Once that was done, we prepared to run the proper schedule and be amazed and delighted by the new performance improvements.<\/p>\n<p>Unfortunately, the whole thing ran like a dog (&#8230; a rather old, sweet but overweight dog with a bad case of asthma). <\/p>\n<p>When I investigated, everything was running serially. I initially thought I&#8217;d screwed something up so tried to work out what I&#8217;d done wrong but, no matter what I tried, the code used parallelism reliably when called from the basic test harness script but, as soon as we called it from the C# application, it would go back to serial. I wondered about session-level parameter settings or different user accounts but there were no identifiable differences there. <\/p>\n<p>Because the performance difference was so great and we were under a lot of pressure to deliver data to the other teams, I was quite worked up by this and frustrated and there was very little out there on Google but perhaps I should have checked My Oracle Support in the first place &#8230;.<\/p>\n<p><a href=\"https:\/\/support.oracle.com\/epmos\/faces\/DocumentDisplay?id=1370527.1\">Attempting to Execute a Parallel DML Statement From an ODP.NET<br \/>\nApplication Using the APPEND or PARALLEL Hint Results in Serial<br \/>\nExecution [ID 1370527.1]<\/a><\/p>\n<p>Ah! That looked pretty similar to what we were seeing. It turned out to be a combination of the way that the Oracle RDBMS works and the default configuration of Oracle Data Provider for .Net (ODP.Net), which sets the <em>enlist<\/em> property to <em>true<\/em>. To quote the support doc &#8211; &#8220;<em>This makes OCI calls which allows the the DML or transactions to become or be promoted to a distributed transaction.<\/em>&#8221; and, as documented in the <a href=\"http:\/\/docs.oracle.com\/cd\/E11882_01\/server.112\/e25494\/ds_txns001.htm#ADMIN12212\">generic RDBMS documentation<\/a>, distributed transactions can&#8217;t use Parallel DML.<\/p>\n<p>As we had no requirement to use distributed transactions, the simple solution was to set enlist=false as a property in the connection string. <\/p>\n<p>Bingo! Everything started running in parallel again &#8230; <\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been doing a lot of work around large volume data loads into an Oracle 11.2 database recently using External Tables and Parallelism and, despite the fact it&#8217;s all used well-known techniques, I think it&#8217;s probably worth a couple of posts to re-emphasise how successful using the right tools for the right job can be.&hellip; <a class=\"more-link\" href=\"http:\/\/orcldoug.com\/blog\/2012\/10\/14\/parallel-dml-and-odp-net\/\">Continue reading <span class=\"screen-reader-text\">Parallel DML and ODP.Net<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1691","post","type-post","status-publish","format-standard","hentry","category-uncategorized","entry"],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":913,"url":"http:\/\/orcldoug.com\/blog\/2005\/11\/04\/resetting-vfilestat-timings\/","url_meta":{"origin":1691,"position":0},"title":"Resetting v$filestat timings","date":"November 4, 2005","format":false,"excerpt":"As I mentioned in a previous blog, I learnt something new from Anjo Kolk's SAN presentation at the Oak Table day at the UKOUG conference. Instead of looking at the maximum read time for a file since the instance started or the average in a statspack report, you can reset\u2026","rel":"","context":"With 2 comments","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1597,"url":"http:\/\/orcldoug.com\/blog\/2014\/05\/02\/statistics-on-partitioned-tables-part-6c-copy_table_stats-bugs-and-patches\/","url_meta":{"origin":1691,"position":1},"title":"Statistics on Partitioned Tables &#8211; Part 6c &#8211; COPY_TABLE_STATS &#8211; Bugs and Patches","date":"May 2, 2014","format":false,"excerpt":"I wanted to talk about a few of the bugs and patches you need to be aware of if you plan to use DBMS_STATS.COPY_TABLE_STATS. Believe me, when entering the world of stats on (sub-)partitioned objects, you had better be prepared to spend a lot of time on My Oracle Support\u2026","rel":"","context":"With 4 comments","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":884,"url":"http:\/\/orcldoug.com\/blog\/2006\/01\/12\/something-else-i-didnt-know\/","url_meta":{"origin":1691,"position":2},"title":"Something Else I Didn&#8217;t Know","date":"January 12, 2006","format":false,"excerpt":"This one is courtesy of Andrew Campbell at Sun Microsystems. He noticed in an Oracle Magazine article that you can use a URL as a script name in sqlplus.SQL> select * from v$version;BANNER----------------------------------------------------------------Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - ProdPL\/SQL Release 10.2.0.1.0 - ProductionCORE 10.2.0.1.0 ProductionTNS for 32-bit Windows:\u2026","rel":"","context":"With 4 comments","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1017,"url":"http:\/\/orcldoug.com\/blog\/2006\/07\/13\/alter-table-move-and-table-stats\/","url_meta":{"origin":1691,"position":3},"title":"alter table &#8230; move and table stats","date":"July 13, 2006","format":false,"excerpt":"Howard Rogers left a comment on my last blog, showing an example of using alter table ... move on a 10gR2 database on Linux. In his example, unlike mine, the table rebuild did not nullify the table's statistics. I admit I was surprised myself when I ran my example yesterday\u2026","rel":"","context":"With 4 comments","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":999,"url":"http:\/\/orcldoug.com\/blog\/2012\/06\/18\/saving-optimiser-stats-9i\/","url_meta":{"origin":1691,"position":4},"title":"Saving Optimiser Stats &#8211; 9i","date":"June 18, 2012","format":false,"excerpt":"In a recent blog I described how a mis-timed optimiser statistics collection job led to a bad execution plan for one of the SQL statements in a regular batch jobIt's no coincidence that we were already in the process of implementing a change to our stats collection period to retain\u2026","rel":"","context":"With 4 comments","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1320,"url":"http:\/\/orcldoug.com\/blog\/2007\/09\/23\/parallel-query-and-11g-part-2\/","url_meta":{"origin":1691,"position":5},"title":"Parallel Query and 11g &#8211; Part 2","date":"September 23, 2007","format":false,"excerpt":"Now, that's weird. A little surprising might be more accurate and maybe I'm missing something.During the various tests with and without parallel hints and different parallel_io_cap_enabled settings, I expected the runs that didn't use parallelism to show up \"db file scattered read\" events in the trace files. For example, here's\u2026","rel":"","context":"With 10 comments","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"http:\/\/orcldoug.com\/blog\/wp-json\/wp\/v2\/posts\/1691","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/orcldoug.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/orcldoug.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/orcldoug.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/orcldoug.com\/blog\/wp-json\/wp\/v2\/comments?post=1691"}],"version-history":[{"count":0,"href":"http:\/\/orcldoug.com\/blog\/wp-json\/wp\/v2\/posts\/1691\/revisions"}],"wp:attachment":[{"href":"http:\/\/orcldoug.com\/blog\/wp-json\/wp\/v2\/media?parent=1691"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/orcldoug.com\/blog\/wp-json\/wp\/v2\/categories?post=1691"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/orcldoug.com\/blog\/wp-json\/wp\/v2\/tags?post=1691"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}