Associative  array binding - poor performance

Dear All
i have very very low performence when i am inserting a binary array using associative array bind. i mean when i insert huge jagged binary array.
the jagged array has
BinarryArray[0][0]........BinarryArray[0][8000]
BinarryArray[1][0]........BinarryArray[1][8000]
BinarryArray[3600][0]........BinarryArray[3600][8000]
BinarryArray[0] - i have 8000 byte end so on. total is 3600 X 8000
that means 28,800KB hence to ~28MB.
the C# code is as follows
string strInsert "Insert Into T Values(t.SEQUENCE.currval, :paramArr);
OracleCommand objCommand = new OracleCommand;
OracleParameter objParam = new OracleParameter(paramArr, OracleDbtype.blob, 8000, system.data.ParameterDirection.Input,true,0,0,"ColumnName", system.data.DataRowVersion.Curren, BinarryArray);
objCommandtext = strInsert;
objCommand.ArrayBindCount = BinarryArray.Length;
objCommand.Parameters.Clear();
objCommand.Parameters.Add(paramArr);
objCommand.ExecuteNonQuery();
In generall the Insertion is good for each row in the array i get separate row in the DB but it works so slow.
why??????
see the code below

well??

Similar Messages

  • Using array binding to perform multiple rowupdates in one pass

    For the first time I am attempting to use array binding in VB.NET to update multiple rows via a single execution of a stored procedure. My subroutine is:
    Friend Sub UpdateSolutionStatusUsingArrays(ByVal intNumBeingUpdated As Integer, ByVal arrScenarioID() As Integer, ByVal arrSolutionID() As Integer, ByVal arrInOrOut() As Integer, ByVal arrTimePeriod() As Integer)
    Try
    'Set up the Command object
    Dim cmdUpdateSolutionStatus As OracleCommand
    cmdUpdateSolutionStatus = New OracleCommand
    cmdUpdateSolutionStatus.CommandType = CommandType.StoredProcedure
    cmdUpdateSolutionStatus.CommandText = "ProcUpdateSolutionStatus"
    cmdUpdateSolutionStatus.Connection = cnnORACLE
    cmdUpdateSolutionStatus.ArrayBindCount = intNumBeingUpdated - 1
    cmdUpdateSolutionStatus.CommandTimeout = CInt(tblOptions.Rows(intDatabaseIndex).Item("ConnectionTimeout"))
    'Add ScenarioID array as parameter
    Dim p_ScenarioID As New OracleParameter("ScenarioID", OracleDbType.Int32)
    p_ScenarioID.Direction = ParameterDirection.Input
    p_ScenarioID.Value = arrScenarioID
    cmdUpdateSolutionStatus.Parameters.Add(p_ScenarioID)
    'Add SolutionID array as parameter
    Dim p_SolutionID As New OracleParameter("SolutionID", OracleDbType.Int32)
    p_SolutionID.Direction = ParameterDirection.Input
    p_SolutionID.Value = arrSolutionID
    cmdUpdateSolutionStatus.Parameters.Add(p_SolutionID)
    'Add InOrOut array as parameter
    Dim p_InOrOut As New OracleParameter("InOrOut", OracleDbType.Int32)
    p_InOrOut.Direction = ParameterDirection.Input
    p_InOrOut.Value = arrInOrOut
    cmdUpdateSolutionStatus.Parameters.Add(p_InOrOut)
    'Add TimePeriod array as parameter
    Dim p_TimePeriod As New OracleParameter("TimePeriod", OracleDbType.Int32)
    p_TimePeriod.Direction = ParameterDirection.Input
    p_TimePeriod.Value = arrTimePeriod
    cmdUpdateSolutionStatus.Parameters.Add(p_TimePeriod)
    'Open connection
    cnnORACLE.Open()
    'Run stored procedure
    cmdUpdateSolutionStatus.ExecuteNonQuery()
    'Tidy up
    cmdUpdateSolutionStatus = Nothing
    cnnORACLE.Close()
    Catch ex As Exception
    WriteLog("Subroutine UpdateSolutionStatusUsingArrays:" & ex.Message.ToString)
    strState = "Error"
    'Update Run Status to show error has occurred
    cnnORACLE.Close()
    UpdateRunStatusORACLE(7)
    End Try
    End Sub
    When the routine tries to run cmdUpdateSolutionStatus.ExecuteNonQuery() I get the error message:
    Unable to cast object of type 'System.Int32[]' to type 'System.IConvertible'.
    I have tried all sorts of variants of the code but with no success. The arrays are being set up correctly. Anyoneone know what I'm missing?
    Stewart

    Try declaring the arrays as OracleNumber datatype instead of Integer. I've had this issue before, and I believe this is what I did to solve the problem.

  • SELECT Command on Associative Array

    Guys,
    I have a question on associative arrays in ORACLE.
    I m working on one assignment where I am not allowed to create any object into the database e.g. Create temporary tables, use of cursors etc.
    For data manipulation i used associative array, but at the end i want to show that result in pl/SQL developer.
    I know that I can't use select command on associative arrays.
    Any alternative/solution for it?
    Also is there any way that i can write the contents of associative array to a .csv file?

    user13478417 wrote:
    I m working on one assignment where I am not allowed to create any object into the database e.g. Create temporary tables, use of cursors etc.Then cease to use Oracle - immediately. As you are violating your assignment constraints.
    ALL SQL and anonymous PL/SQL code blocks you send to Oracle are parsed as cursors. And as you are not allowed to use cursors, it will be impossible to use Oracle as cursors is exactly what Oracle creates... and creates a lot of. For every single SQL statement. And every single anonymous PL./SQL block.
    For data manipulation i used associative array, Why? Arrays is a poor choice in Oracle as a data structure most times as it is inferior in almost every single way to using a SQL table structure instead.
    Pumping data into an array? That already severely limits scalability as the array requires expensive dedicated server (PGA) memory. It does not use the more scalable shared server (SGA) memory.
    Manipulating data in an array? That requires a "+full structure scan+" each time as it does not have the indexing and partitioning features of a SQL table.
    Running a SQL select on an array? That is using a cursor. That also means copying the entire array structure, as bind variable, from the PL/SQL engine to the SQL engine. An excellent way to waste memory resources and slow down performance... but hey you can still shout "+Look Ma, no --brains-- hands, I'm not using any SQL tables as dictated by my assignment!+".... +<sigh>+
    Any alternative/solution for it?You mean besides using Oracle correctly ?
    You could reload the shotgun and shoot yourself in the other foot too. That should distract you for from the pain in the first foot.

  • Associative array comparison and INSERT upon IF condition

    Hi Guys,
    I have written this pl sql code to identify non existing sellers and insert their sales channel information into the dimension table (dimensional table update).
    Somehow,......nothing is inserted and this script runs for 12 hours+ without any result. the sql autotrace shows no result and the explain plan (button on sql developer throws upon clicking "missing keyword". I have no
    information what is going on/wrong. Does anyone spot an error?
    UNDEFINE DimSales;
    UNDEFINE FactTable;
    DEFINE DimSales = 'testsales';
    DEFINE FactTable = 'testfact';
    DECLARE
    v_SellerNo VarChar(9);
    v_error_code T_ERRORS.v_error_code%TYPE;
    v_error_message T_ERRORS.v_error_message%TYPE;
    TYPE assoc_array_str_type1 IS TABLE OF VARCHAR2(32) INDEX BY PLS_INTEGER;
         v1 assoc_array_str_type1;
    TYPE assoc_array_str_type2 IS TABLE OF VARCHAR2(32) INDEX BY PLS_INTEGER;
         v2 assoc_array_str_type2;
    BEGIN
    --Collect all distinct SellerNo into associative array (hash table)
    select distinct SellerNo bulk collect into v1 from &FactTable;
    select distinct seller_id bulk collect into v2 from &DimSales;
    v_SellerNo := v1.first;
    loop
    exit when v1 is null;
    --1 Check if v_SellerNo already exists in DIM_Sales (if NOT/FALSE, its a new seller and we can insert all records for that seller
    if (v2.exists(v_SellerNo)=false) THEN
    INSERT INTO &DimSales (K_Sales,REG,BVL,DS, VS,RS,GS,VK)
    (SELECT DISTINCT trim(leading '0' from RS||GS) ,REG BVL,DS,VS,RS,GS,VK from &FactTable where SellerNo =v_SellerNo);
    --ELSE
    end if;
    v_SellerNo := v1.next(v_SellerNo);
    end loop;
    EXCEPTION
    WHEN OTHERS THEN
    ROLLBACK;
    --v_error_code := SQLCODE
    --v_error_message := SQLERRM
    --INSERT INTO t_errors VALUES ( v_error_code, v_error_message);
    END;
    ---------------------------------------------------------------

    Distinct clause requires a sort. Sorts can be very expensive.
    Bulk collects that are not constrained in fetch size, can potentially fetch millions of rows - requiring that data to be wholly read into server memory. I have seen how this can degrade performance so badly that the kernel reboots the server.
    Using PL/SQL loops to process and insert/update/delete data is often problematic due to its row-by-row approach - also called slow-by-slow approach. It is far more scalable letting SQL do the "loop" processing, by using joins, sub-selects and so on.
    Where the conditional processing is too complex for SQL to handle, then PL/SQL is obviously an alternative to use. Ideally one should process data sets as oppose to rows in PL//SQL. Reduce context switching by using bulk fetches and bulk binds.
    But PL/SQL cannot execute in parallel as the SQL it fires off can. If after all the optimisation, the PL/SQL process still needs to hit a million rows to process, it will be slow irrespective of how optimal that PL/SQL approach and design - simply because of the number of rows and the processing overheads per row.
    In that case, the PL/SQL code itself need to be parallelised. There are a number of ways to approach this problem - the typical one is to create unique and distinct ranges of rows to process, spawn multiple P/SQL processes, and provide each with a unique range of rows to process. In parallel.
    So you need to look close at what you are trying to achieve, what the workloads are, and how to effectively decrease the workloads and increase the processing time of a workload.
    For example - finding distinct column values. You can pay for that workload when wanting that distinct list. And each time afterward repeat that workload when wanting that distinct list. Or you can pay for that workload up-front with the DML that creates/updates those values - and use (for example) a materialised view to maintain a ready to use distinct list of values.
    Same workload in essence - but paying once for it and up-front as oppose to each time you execute your code that needs to dynamically build that distinct list.
    Kent Crotty did tests and showed stunning performance improvements with bulk collect and forall, up to 30x faster:Bulk processing is not a magical silver bullet. It is a tool. And when correctly use, the tool does exactly what it was designed to do.
    The problem is using a hammer to drive in screws - instead of a screwdriver. There's nothing "stunning" about using a screwdriver. It is all about using the correct tool.
    If the goal of the swap daemon is to free up "idle" chunks of memory, and try to use that memory for things like file cache instead, what does that have to do with bulk processing?The swap daemon reads virtual memory pages from swap space into memory, and writes virtual pages from memory to swap space.
    What does it have to do with bulk processing? A bulk fetch reads data from the SGA (buffer cache) into the PGA (private process memory space). The larget the fetch, the more memory is required. If for example 50% of server memory is required for a bulk collection that is 2GB in size, then that will force in-use pages from memory to swap space.. only to be swapped back again as it is needed, thereby forcing other in-use pages to swap. The swap daemon will consume almost all the CPU time swapping hot pages continually in and out of memory.

  • Procedure Array Binding a Null Value

    Can you perform array binding in ODP.NET (to a procedure for example that inserts values) and assume that if there are null values in the array that the records inserted will have the corresponding null values in their records?

    Here's a quick sample using pl/sql associative arrays to insert null values into a table (I think this is what you mean)...
    SQL*Plus: Release 10.1.0.3.0 - Production on Fri Feb 18 09:38:55 2005
    Copyright (c) 1982, 2004, Oracle.  All rights reserved.
    SQL> connect /
    Connected.
    SQL> create table null_array_insert
      2  (
      3    first_name  varchar2(32) not null,
      4    middle_name varchar2(32) null,
      5    last_name   varchar2(32) not null
      6  );
    Table created.
    SQL> create or replace package null_array_test as
      2    -- create a type for each column
      3    type t_first_name is table of null_array_insert.first_name%type
      4      index by binary_integer;
      5
      6    type t_middle_name is table of null_array_insert.middle_name%type
      7      index by binary_integer;
      8
      9    type t_last_name is table of null_array_insert.last_name%type
    10      index by binary_integer;
    11
    12    -- the procedures that will perform our work
    13    procedure bulk_insert (p_first_name  in t_first_name,
    14                           p_middle_name in t_middle_name,
    15                           p_last_name   in t_last_name);
    16  end null_array_test;
    17  /
    Package created.
    SQL> create or replace package body null_array_test as
      2    procedure bulk_insert (p_first_name  in t_first_name,
      3                           p_middle_name in t_middle_name,
      4                           p_last_name   in t_last_name) is
      5    begin
      6      forall i in p_first_name.first..p_first_name.last
      7      insert into null_array_insert (first_name,
      8                                     middle_name,
      9                                     last_name)
    10                          values    (p_first_name(i),
    11                                     p_middle_name(i),
    12                                     p_last_name(i));
    13    end bulk_insert;
    14  end null_array_test;
    15  /
    Package body created.
    Here's the C# code:
    using System;
    using System.Data;
    using Oracle.DataAccess.Client;
    using Oracle.DataAccess.Types;
    namespace Associative
      /// <summary>
      /// Summary description for Class1.
      /// </summary>
      class Class1
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
          string connStr = "User Id=/";
          OracleConnection oraConn = new OracleConnection(connStr);
          oraConn.Open();
          // create the command object and set attributes
          OracleCommand cmd = new OracleCommand("null_array_test.bulk_insert", oraConn);
          cmd.CommandType = CommandType.StoredProcedure;
          // create parameter objects for each parameter
          OracleParameter p_first_name = new OracleParameter();
          OracleParameter p_middle_name = new OracleParameter();
          OracleParameter p_last_name = new OracleParameter();
          // set parameter type for each parameter
          p_first_name.OracleDbType = OracleDbType.Varchar2;
          p_middle_name.OracleDbType = OracleDbType.Varchar2;
          p_last_name.OracleDbType = OracleDbType.Varchar2;
          // set the collection type for each parameter
          p_first_name.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
          p_middle_name.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
          p_last_name.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
          // set the parameter values
          p_first_name.Value = new string[4]{"First 1", "First 2", "First 3", "First 4"};
          p_middle_name.Value = new string[4]{"Middle 1", "", "Middle 3", ""};
          p_last_name.Value = new string[4]{"Last 1", "Last 2", "Last 3", "Last 4"};
          // set the size for each array
          p_first_name.Size = 4;
          p_middle_name.Size = 4;
          p_last_name.Size = 4;
          // set array bind size for the columns since they
          // are a variable size type (varchar2)
          p_first_name.ArrayBindSize = new int[4]{32, 32, 32, 32};
          p_middle_name.ArrayBindSize = new int[4]{32, 32, 32, 32};
          p_last_name.ArrayBindSize = new int[4]{32, 32, 32, 32};
          // add the parameters to the command object
          cmd.Parameters.Add(p_first_name);
          cmd.Parameters.Add(p_middle_name);
          cmd.Parameters.Add(p_last_name);
          // execute the insert
          cmd.ExecuteNonQuery();
          p_last_name.Dispose();
          p_middle_name.Dispose();
          p_first_name.Dispose();
          cmd.Dispose();
          oraConn.Dispose();
    And after running the code:
    SQL> select * from null_array_insert;
    FIRST_NAME                       MIDDLE_NAME                      LAST_NAME
    First 1                          Middle 1                         Last 1
    First 2                                                           Last 2
    First 3                          Middle 3                         Last 3
    First 4                                                           Last 4
    4 rows selected.
    SQL> select * from null_array_insert where middle_name is null;
    FIRST_NAME                       MIDDLE_NAME                      LAST_NAME
    First 2                                                           Last 2
    First 4                                                           Last 4
    2 rows selected.
    SQL>Hope that helps,
    - Mark

  • Associative array type for each blob column in the table

    i am using the code in given link
    http://www.oracle.com/technology/oramag/oracle/07-jan/o17odp.html
    i chnages that code like this
    CREATE TABLE JOBS
    JOB_ID VARCHAR2(10 BYTE),
    JOB_TITLE VARCHAR2(35 BYTE),
    MIN_SALARY NUMBER(6),
    MAX_SALARY NUMBER(6),
    JOBPIC BLOB
    CREATE OR REPLACE PACKAGE associative_array
    AS
    -- define an associative array type for each column in the jobs table
    TYPE t_job_id IS TABLE OF jobs.job_id%TYPE
    INDEX BY PLS_INTEGER;
    TYPE t_job_title IS TABLE OF jobs.job_title%TYPE
    INDEX BY PLS_INTEGER;
    TYPE t_min_salary IS TABLE OF jobs.min_salary%TYPE
    INDEX BY PLS_INTEGER;
    TYPE t_max_salary IS TABLE OF jobs.max_salary%TYPE
    INDEX BY PLS_INTEGER;
    TYPE t_jobpic IS TABLE OF jobs.jobpic%TYPE
    INDEX BY PLS_INTEGER;
    -- define the procedure that will perform the array insert
    PROCEDURE array_insert (
    p_job_id IN t_job_id,
    p_job_title IN t_job_title,
    p_min_salary IN t_min_salary,
    p_max_salary IN t_max_salary,
    p_jobpic IN t_jobpic
    END associative_array;
    CREATE OR REPLACE package body SHC_OLD.associative_array as
    -- implement the procedure that will perform the array insert
    procedure array_insert (p_job_id in t_job_id,
    p_job_title in t_job_title,
    p_min_salary in t_min_salary,
    p_max_salary in t_max_salary,
    P_JOBPIC IN T_JOBPIC
    ) is
    begin
    forall i in p_job_id.first..p_job_id.last
    insert into jobs (job_id,
    job_title,
    min_salary,
    max_salary,
    JOBPIC
    values (p_job_id(i),
    p_job_title(i),
    p_min_salary(i),
    p_max_salary(i),
    P_JOBPIC(i)
    end array_insert;
    end associative_array;
    this procedure is called from .net. from .net sending blob is posiible or not.if yes how

    Ok, that won't work...you need to generate an image tag and provide the contents of the blob column as the src for the image tag.
    If you look at my blog entry -
    http://jes.blogs.shellprompt.net/2007/05/18/apex-delivering-pages-in-3-seconds-or-less/
    and download that Whitepaper that I talk about you will find an example of how to do what you want to do. Note the majority of that whitepaper is discussing other (quite advanced) topics, but there is a small part of it that shows how to display an image stored as a blob in a table.

  • Inserting a associative array into a table

    Hi,
    I am working on a process where I want to store the temporary results in an associative array. At the end of the process I plan to write the contents of the array into a table that has the same structure. (the array is defined as a %rowtype of the table)
    Is it possible to execute ONE sql statement that transfers the array into the table? I am on 10g (10.2.0.4.0)
    Here's what I have now:
    declare
      type t_emp is table of emp%rowtype index by pls_integer;
      v_emp t_emp;
    begin
      -- a process that fills v_emp with lots of data
      for i in v_emp.first .. v_emp.last
      loop
        insert into emp values v_emp(i);
      end loop;  
    end;But it would be better if the loop could be replaced by sql one statement that inserts all of v_emp into emp. Is that possible?
    Thanks!
    PS: I'm not sure whether it's a good idea to use this approach... building a table in memory and inserting it into the database at the end of the process. Maybe it's better to insert every record directly into the table... but in any case I'm curious to see if it is possible in theory :)
    Edited: Added version info

    True, SQL cannot access the PL/SQL type.
    So you can not do something like this:
    insert into emp
    select * from table(v_emp)That is not possible.
    But FORALL is possible:
    FORALL i in v_emp.first .. v_emp.last
        insert into emp values v_emp(i);FORALL makes just one "round trip" to SQL bulk binding the entire contents of the array.
    It is much more efficient than the normal FOR loop, though it is mostly a PL/SQL optimization - even the FORALL actually inserts the rows "one at the time", it just hands the entire array to the SQL engine in one go.
    If the logic has to be done procedurally, FORALL is efficient.
    If the logic can be changed so arrays can be avoided completely and everything done in a single "insert into ... select ..." statement, that is the most efficient.

  • Poor performance and high number of gets on seemingly simple insert/select

    Versions & config:
    Database : 10.2.0.4.0
    Application : Oracle E-Business Suite 11.5.10.2
    2 node RAC, IBM AIX 5.3Here's the insert / select which I'm struggling to explain why it's taking 6 seconds, and why it needs to get > 24,000 blocks:
    INSERT INTO WF_ITEM_ATTRIBUTE_VALUES ( ITEM_TYPE, ITEM_KEY, NAME, TEXT_VALUE,
      NUMBER_VALUE, DATE_VALUE ) SELECT :B1 , :B2 , WIA.NAME, WIA.TEXT_DEFAULT,
      WIA.NUMBER_DEFAULT, WIA.DATE_DEFAULT FROM WF_ITEM_ATTRIBUTES WIA WHERE
      WIA.ITEM_TYPE = :B1
    call     count       cpu    elapsed       disk      query    current        rows
    Parse        1      0.00       0.00          0          0          4           0
    Execute      2      3.44       6.36          2      24297        198          36
    Fetch        0      0.00       0.00          0          0          0           0
    total        3      3.44       6.36          2      24297        202          36
    Misses in library cache during parse: 1
    Misses in library cache during execute: 2Also from the tkprof output, the explain plan and waits - virtually zero waits:
    Rows     Execution Plan
          0  INSERT STATEMENT   MODE: ALL_ROWS
          0   TABLE ACCESS   MODE: ANALYZED (BY INDEX ROWID) OF 'WF_ITEM_ATTRIBUTES' (TABLE)
          0    INDEX   MODE: ANALYZED (RANGE SCAN) OF 'WF_ITEM_ATTRIBUTES_PK' (INDEX (UNIQUE))
    Elapsed times include waiting on following events:
      Event waited on                             Times   Max. Wait  Total Waited
      ----------------------------------------   Waited  ----------  ------------
      library cache lock                             12        0.00          0.00
      gc current block 2-way                         14        0.00          0.00
      db file sequential read                         2        0.01          0.01
      row cache lock                                 24        0.00          0.01
      library cache pin                               2        0.00          0.00
      rdbms ipc reply                                 1        0.00          0.00
      gc cr block 2-way                               4        0.00          0.00
      gc current grant busy                           1        0.00          0.00
    ********************************************************************************The statement was executed 2 times. I know from slicing up the trc file that :
    exe #1 : elapsed = 0.02s, query = 25, current = 47, rows = 11
    exe #2 : elapsed = 6.34s, query = 24272, current = 151, rows = 25
    If I run just the select portion of the statement, using bind values from exe #2, I get small number of gets (< 10), and < 0.1 secs elapsed.
    If I make the insert into an empty, non-partitioned table, I get :
    call     count       cpu    elapsed       disk      query    current        rows
    Parse        1      0.00       0.00          0          0          0           0
    Execute      1      0.01       0.08          0        137         53          25
    Fetch        0      0.00       0.00          0          0          0           0
    total        2      0.01       0.08          0        137         53          25and same explain plan - using index range scan on WF_Item_Attributes_PK.
    This problem is part of testing of a database upgrade and country go-live. On a 10.2.0.3 test system (non-RAC), the same insert/select - using the real WF_Item_Attributes_Value table takes :
    call     count       cpu    elapsed       disk      query    current        rows
    Parse        1      0.00       0.00          0          0          0           0
    Execute      1      0.00       0.10         10         27        136          25
    Fetch        0      0.00       0.00          0          0          0           0
    total        2      0.00       0.10         10         27        136          25So I'm struggling to understand why the performance on the 10.2.0.4 RAC system is so much worse for this query, and why it's doing so many gets. Suggestions, thoughts, ideas welcomed.
    I've verified system level things - CPUs weren't/aren't max'd out, no significant paging/swapping activity, run queue not long. AWR report for the time period shows nothing unusual.
    further info on the objects concerned:
    query source table :
    WF_Item_Attributes_PK : unique index on Item_Type, Name. Index has 144 blocks, non-partitioned
    WF_Item_Attributes tbl : non-partitioned, 160 blocks
    insert destination table:
    WF_Item_Attribute_Values:
    range partitioned on Item_Type, and hash sub-partitioned on Item_Key
    both executions of the insert hit the partition with the most data : 127,691 blocks total ; 8 sub-partitions with 15,896 to 16,055 blocks per sub-partition.
    WF_Item_Attribute_Values_PK : unique index on columns Item_Type, Item_Key, Name. Range/hash partitioned as per table.
    Bind values:
    exe #1 : Item_Type (:B1) = OEOH, Item_Key (:B2) = 1048671
    exe #2 : Item_Type (:B1) = OEOL, Item_Key (:B2) = 4253168
    number of rows in WF_Item_Attribute_Values for Item_Type = OEOH : 1132587
    number of rows in WF_Item_Attribute_Values for Item_Type = OEOL : 18763670
    The non-RAC 10.2.0.3 test system (clone of Production from last night) has higher row counts for these 2.
    thanks and regards
    Ivan

    hi Sven,
    Thanks for your input.
    1) I guess so, but I haven't lifted the lid to delve inside the form as to which one. I don't think it's the cause though, as I got poor performance running the insert statement with my own value (same statement, using my own bind value).
    2) In every execution plan I've seen, checked, re-checked, it uses a range scan on the primary key. It is the most efficient I think, but the source table is small in any case - table 160 blocks, PK index 144 blocks. So I think it's the partitioned destination table that's the problem - but we only see this issue on the 10.2.0.4 pre-production (RAC) system. The 10.2.0.3 (RAC) Production system doesn't have it. This is why it's so puzzling to me - the source table read is fast, and does few gets.
    3) table storage details below - the Item_Types being used were 'OEOH' (fast execution) and 'OEOL' (slow execution). Both hit partition WF_ITEM49, hence I've only expanded the subpartition info for that one (there are over 600 sub-partitions).
    ============= From DBA_Part_Tables : Partition Type / Count =============
    PARTITI SUBPART PARTITION_COUNT DEF_TABLESPACE_NAME
    RANGE   HASH                 77 APPS_TS_TX_DATA
    1 row selected.
    ============= From DBA_Tab_Partitions : Partition Names / Tablespaces =============
    Partition Name       TS Name         High Value           High Val Len
    WF_ITEM1             APPS_TS_TX_DATA 'A1'                            4
    WF_ITEM2             APPS_TS_TX_DATA 'AM'                            4
    WF_ITEM3             APPS_TS_TX_DATA 'AP'                            4
    WF_ITEM47            APPS_TS_TX_DATA 'OB'                            4
    WF_ITEM48            APPS_TS_TX_DATA 'OE'                            4
    WF_ITEM49            APPS_TS_TX_DATA 'OF'                            4
    WF_ITEM50            APPS_TS_TX_DATA 'OK'                            4
    WF_ITEM75            APPS_TS_TX_DATA 'WI'                            4
    WF_ITEM76            APPS_TS_TX_DATA 'WS'                            4
    WF_ITEM77            APPS_TS_TX_DATA MAXVALUE                        8
    77 rows selected.
    ============= From dba_part_key_columns : Partition Columns =============
    NAME                           OBJEC Column Name                    COLUMN_POSITION
    WF_ITEM_ATTRIBUTE_VALUES       TABLE ITEM_TYPE                                    1
    1 row selected.
    PPR1 sql> @q_tabsubpart wf_item_attribute_values WF_ITEM49
    ============= From DBA_Tab_SubPartitions : SubPartition Names / Tablespaces =============
    Partition Name       SUBPARTITION_NAME              TS Name         High Value           High Val Len
    WF_ITEM49            SYS_SUBP3326                   APPS_TS_TX_DATA                                 0
    WF_ITEM49            SYS_SUBP3328                   APPS_TS_TX_DATA                                 0
    WF_ITEM49            SYS_SUBP3332                   APPS_TS_TX_DATA                                 0
    WF_ITEM49            SYS_SUBP3331                   APPS_TS_TX_DATA                                 0
    WF_ITEM49            SYS_SUBP3330                   APPS_TS_TX_DATA                                 0
    WF_ITEM49            SYS_SUBP3329                   APPS_TS_TX_DATA                                 0
    WF_ITEM49            SYS_SUBP3327                   APPS_TS_TX_DATA                                 0
    WF_ITEM49            SYS_SUBP3325                   APPS_TS_TX_DATA                                 0
    8 rows selected.
    ============= From dba_part_key_columns : Partition Columns =============
    NAME                           OBJEC Column Name                    COLUMN_POSITION
    WF_ITEM_ATTRIBUTE_VALUES       TABLE ITEM_KEY                                     1
    1 row selected.
    from DBA_Segments - just for partition WF_ITEM49  :
    Segment Name                        TSname       Partition Name       Segment Type     BLOCKS     Mbytes    EXTENTS Next Ext(Mb)
    WF_ITEM_ATTRIBUTE_VALUES            @TX_DATA     SYS_SUBP3332         TblSubPart        16096     125.75       1006         .125
    WF_ITEM_ATTRIBUTE_VALUES            @TX_DATA     SYS_SUBP3331         TblSubPart        16160     126.25       1010         .125
    WF_ITEM_ATTRIBUTE_VALUES            @TX_DATA     SYS_SUBP3330         TblSubPart        16160     126.25       1010         .125
    WF_ITEM_ATTRIBUTE_VALUES            @TX_DATA     SYS_SUBP3329         TblSubPart        16112    125.875       1007         .125
    WF_ITEM_ATTRIBUTE_VALUES            @TX_DATA     SYS_SUBP3328         TblSubPart        16096     125.75       1006         .125
    WF_ITEM_ATTRIBUTE_VALUES            @TX_DATA     SYS_SUBP3327         TblSubPart        16224     126.75       1014         .125
    WF_ITEM_ATTRIBUTE_VALUES            @TX_DATA     SYS_SUBP3326         TblSubPart        16208    126.625       1013         .125
    WF_ITEM_ATTRIBUTE_VALUES            @TX_DATA     SYS_SUBP3325         TblSubPart        16128        126       1008         .125
    WF_ITEM_ATTRIBUTE_VALUES_PK         @TX_IDX      SYS_SUBP3332         IdxSubPart        59424     464.25       3714         .125
    WF_ITEM_ATTRIBUTE_VALUES_PK         @TX_IDX      SYS_SUBP3331         IdxSubPart        59296     463.25       3706         .125
    WF_ITEM_ATTRIBUTE_VALUES_PK         @TX_IDX      SYS_SUBP3330         IdxSubPart        59520        465       3720         .125
    WF_ITEM_ATTRIBUTE_VALUES_PK         @TX_IDX      SYS_SUBP3329         IdxSubPart        59104     461.75       3694         .125
    WF_ITEM_ATTRIBUTE_VALUES_PK         @TX_IDX      SYS_SUBP3328         IdxSubPart        59456      464.5       3716         .125
    WF_ITEM_ATTRIBUTE_VALUES_PK         @TX_IDX      SYS_SUBP3327         IdxSubPart        60016    468.875       3751         .125
    WF_ITEM_ATTRIBUTE_VALUES_PK         @TX_IDX      SYS_SUBP3326         IdxSubPart        59616     465.75       3726         .125
    WF_ITEM_ATTRIBUTE_VALUES_PK         @TX_IDX      SYS_SUBP3325         IdxSubPart        59376    463.875       3711         .125
    sum                                                                                               4726.5
    [the @ in the TS Name is my shortcode, as Apps stupidly prefixes every ts with "APPS_TS_"]
    The Tablespaces used for all subpartitions are UNIFORM extent mgmt, AUTO segment_space_management ; LOCAL extent mgmt.regards
    Ivan

  • How to share an associative array throughout the entire instance?

    Hi all,
    I have an associative array with much data, and it would barely change, I want to keep it in the memory and share it throughout the entire instance, and make sure all sessions of all users get the same associative array, is it possible?
    Thanks in advanced.

    >
    I want to keep it in the memory and share it throughout the entire instance, and make sure all sessions of all users get the same associative array, is it possible?
    Why do you want to keep it in memory?
    Will using a table for that, which being accessed frequently, will practically always be in the buffer cache, cause performance problems for you?
    The only other way to keep data in memory globally accesable to all database sessions is to use the global application context feature. With that you can store [name;value] pairs in memory and easily access (read) them using the SYS_CONTEXT built-in.
    Toon

  • Associative Arrays, Indexes vs. Full Table Scans

    Hello,
    I just started using ODP.Net to connect my .Net Web Service to our Oracle Database. The reason why I switched to ODP.Net is support for arrays. If I wanted to pass in arrays to the procedure I had to pass it in through a varchar2 in a CSV formatted string.
    ex. "123,456,789"
    So now I'm using ODP.net, passing in PL/SQL Associative Arrays then converting those arrays to nested tables to use within queries.
    ex.
    OPEN OUT_CURSOR FOR
    SELECT COLUMN1, COLUMN2
    WHERE COLUMN_ID IN (SELECT ID FROM TABLE(CAST(ASSOC_ARR_TO_NESTED(IN_ASSOC_ARR) AS NESTED_TBL_TYPE)))
    It uses the array successfully however what it doesn't do is use the index on the table. Running the same query without arrays uses the index.
    My colleague who works more on the Oracle side has posted this issue in the database general section (link below). I'm posting here because it does seem that it is tied to ODP.Net.
    performance - index not used when call from service
    Has anyone ever experienced this before?

    You have to use a cardinality hint to force Oracle to use the index:
    /*+ cardinality(tab 10) */See How to use OracleParameter whith the IN Operator of select statement

  • PL/SQL Associative Array as INPUT Parameter

    Hi,
    Just wondering if anyone out there has a good example of how to get VB.NET (using ODP.NET 9.2.0.4) to pass an Associative Array as an Input parameter to a stored procedure (not for bulk binds)? Specifically, I'm looking for an example of how a VB Strong Typed Collection would be passed through the PLSQLAssociativeArray Collection Type.
    I've managed to get a test to work by passing a 1-D String Array through the ODP.NET layer to the PL/SQL AssociativeArray parameter. But I've had zero success trying to get the Collection from VB through ODP.NET.
    Thanks in advance for any help.
    Todd.

    For example, if I wanted to return a list of customer ids and names into A PLSQL Associative Array, how would I do it. I know how to return a list of customer ids into a PLSQL associative aray using the code below but I have to specify the maximum number of elements and the maximum size of each of the elements. Is there any way around this?
    Dim prmOutCustomerIdList As New OracleParameter
    With prmOutCustomerIdList
    .ParameterName = "oCustomerIdList"
    .CollectionType = OracleCollectionType.PLSQLAssociativeArray
    .OracleDbType = OracleDbType.Varchar2
    .Direction = ParameterDirection.Output
    .Size = 5
    .ArrayBindSize = New Integer(4) {10, 10, 10, 10, 10}
    End With

  • How to isolate poor performance caused by NETWORK

    Hi Friends,
    I would like to know a way to isolate sql server bad query performance is caused by NETWORK and not the sql server.
    Are there any specific tips and tricks in ssms, waitype of specific perfmon counter permissable values for network is concerned? How to baseline the network related counters and what values should I consider as good /better/poor.
    Any help would be appreciated.
    Thank you.

    You need to talk to the network manager about testing network performance.
    Related blog: "As you may already be aware, the ASYNC_NETWORK_IO (seen in SQL 2005) and NETWORKIO (seen in SQL 2000) wait types are associated with either a calling application that is not processing results quickly enough from SQL
    Server or is associated with a network performance issue."
    LINK:
    http://blogs.msdn.com/b/joesack/archive/2009/01/09/troubleshooting-async-network-io-networkio.aspx
    ASYNCH_NETWORK_IO wiki:
    http://mssqlwiki.com/sqlwiki/sql-performance/async_network_io-or-network_io/
    Kalman Toth Database & OLAP Architect
    IPAD SELECT Query Video Tutorial 3.5 Hours
    New Book / Kindle: Exam 70-461 Bootcamp: Querying Microsoft SQL Server 2012

  • PL/SQL Associative Arrays Plus.

    Hello, in the next version of ODP.NET support for PL/SQL Associative Arrays of Records ?
    Roberto.

    It's not a direct example of calling a SP that takes a VARRAY of OBJECTs, but it should get you headed down the right path:
    http://www.oracle.com/technology/obe/hol08/dotnet/udt/udt_otn.htm
    However, for performance reasons you should certainly consider using Associative Arrays even if this means slicing up your RECORDs into multiple arrays of each one containing a field of the RECORD. You can do a performance comparison of this technique vs using VARRAYS with your particular data to see if this is required.

  • How do u create a datatable from PLSQL Associative Arrays returned from SP

    Using C# 4.0 ODP.NET 11g, vs2010 on Windows XP.
    Have a procedure that takes two input values and returns 35 PL\SQL Associative Arrays (pl/sql tables). I am currently able to call the proc and have it returned the values. i end up with 35 arrays each 35 elements in length.
    I want to create a datatable from them but am at a lost on how to do so.
    This what i have
    Oracle.DataAccess.Client.OracleCommand oCommand = new Oracle.DataAccess.Client.OracleCommand();
    oCommand.CommandText = ProcName;
    oCommand.CommandType = CommandType.StoredProcedure;
    //Input Parameters
    OracleParameter param1 = oCommand.Parameters.Add("p_orderid",OracleDbType.Int32);
    param1.Direction = ParameterDirection.Input;
    param1.Value = OrderID;
    OracleParameter param2 = oCommand.Parameters.Add("p_testinstanceid", OracleDbType.Int32);
    param2.Direction = ParameterDirection.Input;
    param2.Value = TestInstanceID;
    //Output Parameters
    OracleParameter param3 = oCommand.Parameters.Add("program_id", OracleDbType.Int32);
    param3.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
    param3.Direction = ParameterDirection.Output;
    param3.Size = 50;
    OracleParameter param4 = oCommand.Parameters.Add("normyear", OracleDbType.Varchar2);
    param4.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
    param4.Direction = ParameterDirection.Output;
    param4.Size = 50;
    param4.ArrayBindSize = new int[50];
    // set the bind size value for each element
    for (int i = 0; i < 50; i++)
    param4.ArrayBindSize[i] = 10;
    ...33 more output parameters all PLSQLAssociativeArray type
    oCommand.ExecuteNonQuery();
    OracleDataAdapter da = new OracleDataAdapter(oCommand);
    //Fill the DataTable
    da.Fill(dt);
    The datatable is empty. What am i doing wrong? Or this there a better way to get the output values to end up in a datatable. Note that when i examine the parameters in oCommand i see that they all the the right out values.

    I have multiple where conditions which needs the same subqueryThat is where the Subquery Factoring Clause comes in handy, because then
    »Oracle Database optimizes the query by treating the query name as either an inline view or as a temporary table«
    with temp as (
    subquery
    select 1
      from table1
    where col1 in (select * from temp)
       and col2 in (select * from temp)
       and col3 in (select * from temp)

  • Array Bind: nbr of updated rows?

    Hello,
    when using array binding with UPDATE statements, how to look up the number of updated rows?
    I couldn't find any parameter property such as ArrayBindAffectedRows.
    Is it possible to use array bind with SQL statements which return values, e.g.:
    UPDATE emp SET salary = salary + :increase
    WHERE mgr = :mgrNo
    RETURNING salary INTO :newSalary;
    Hm, arrays :increase and :newSalary might have different lengths.
    Thanks,
    Armin

    Ok this is genuinly tricky.
    The only way I can think of to get this is to use FORALL and BULK COLLECT. This does an array-bound insert from PL/SQL. But you need to pass Associative Arrays from ODP.NET to PL/SQL to get this started.
    Any other solution I could think of would require running some PL/SQL code for each update statement, for instance in a trigger. But avoiding the context switches from PL/SQL to SQL is a main reason to use array binding in the first place.
    Here's a complete sample program:
    I used inline PL/SQL for compactness, but you might want to save the block as a procedure.
    using System;
    using System.Data;
    using Oracle.DataAccess.Client;
    using Oracle.DataAccess.Types;
         public class Test
          static OracleConnection connect()
            string constr = "data source=oracle;user id=scott;password=tiger";
            OracleConnection con = new OracleConnection(constr);
            con.Open();
            return con;
        const string sql = @"
    declare
      type NumTable is table of Number index by binary_integer;
      l_managers NumTable := :mgr;
      l_increase NumTable := :inc;
      l_newSals NumTable;
      l_records int;
    begin
      forall idx in l_managers.first .. l_managers.last
        update emp
        SET
        sal = sal + l_increase(idx)
        WHERE mgr = l_managers(idx)
        RETURNING sal BULK COLLECT INTO l_newSals;
      :records_affected := l_newSals.count;
    end;
        [STAThread]
        static void Main(string[] args)
          try
            using (OracleConnection con = connect())
              string cr = new String(new char[] {(char)13});
              OracleCommand cmd = new OracleCommand(sql.Replace(cr,""),con);
              OracleDecimal[] increases = new OracleDecimal[] {10,20,30};
              int[] managers = new int[] { 7698,7839,7782};
             OracleParameter pMgr = cmd.Parameters.Add("manager",
                 OracleDbType.Int32,
                 ParameterDirection.Input);
              pMgr.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
              pMgr.Size = managers.Length;
              pMgr.Value = managers;
              OracleParameter pInc = cmd.Parameters.Add("increase",
                 OracleDbType.Decimal,
                 ParameterDirection.Input);
              pInc.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
              pInc.Size = increases.Length;
              pInc.Value = increases;
              OracleParameter pRecs = cmd.Parameters.Add("records",
                 OracleDbType.Int32 ,
                 ParameterDirection.Output);
              pRecs.CollectionType = OracleCollectionType.None;
              cmd.ExecuteNonQuery();
              int recs = (int)pRecs.Value;
              Console.WriteLine("{0} records affected",recs );
          catch (Exception ex)
            Console.WriteLine(ex);
    }

Maybe you are looking for

  • System not clearing the Payment request items with the payments

    HI Everybody, User getting an issue relating to clearing of the payment request items. In a particular Contract account, it has got 51.75 Pounds of Bank Giro incoming payment. It has contains some 5 items of payment, 3 items of 10.75 and 1 Item of 21

  • Error handling in post-mapping (10gR2)

    Hi all, I raised an application error in a procedure executed in post-mapping with : raise_application_error (-20001, varMessage) ; but when it raised the mapping is not marked on error and there is nothing in the mapping execution details displayed

  • Correct sequence settings

    Hi, I'm working on a video to be posted on internet, in a "webtv" that uses videos with the format of 396 x 270. I filmed in a HD camara, 1920 x 1080. I'm setting the sequence to 792 x 540 (twice the size of the webtv screen just because if later I d

  • Manual Nat (twice Nat) Answers

    There seems to be a large number of the subject queries in one form or another.  Having acquired an asa 5505 and using 8.43 firmware and the ADSM gui for router configuration it has not been an easy transition from other products.   I have come to un

  • Can I download Adobe flash onto an iPad

    iis there a way to download Adobe flash onto an IPad?