Хранимая процедура в Oracle и IDataReader.Read () в VB.NET - PullRequest
0 голосов
/ 21 сентября 2011

У меня есть хранимая процедура, которая кажется очень медленной.

Выполнение ее в Oracle SQL Developer;

SET TIMING ON;

DECLARE
  CUR_OUT UTILS.T_CURSOR;
  P_ARTTYID NUMBER;
  P_ORDERST VARCHAR2(200);
  P_DRUMNO VARCHAR2(200);
  P_SHIPPINGNO VARCHAR2(200);
  P_DELIVERYDATEFROM DATE;
BEGIN
  P_ARTTYID := 2;
  P_ORDERST := '3';
  P_DRUMNO := '611-480';
  P_SHIPPINGNO := NULL;
  P_DELIVERYDATEFROM := '2005-01-01';

  C_T_ORDER_GETOVERVIEW(
    CUR_OUT => CUR_OUT,
    P_ARTTYID => P_ARTTYID,
    P_ORDERST => P_ORDERST,
    P_DRUMNO => P_DRUMNO,
    P_SHIPPINGNO => P_SHIPPINGNO,
    P_DELIVERYDATEFROM => P_DELIVERYDATEFROM
  );

  --DBMS_OUTPUT.PUT_LINE('CUR_OUT = ' || CUR_OUT); -- Doesn´t work ;|
END;

Дает «Выходные данные оператора»

anonymous block completed
139ms elapsed

Теперь проблема заключается в том, что я вызываю его из приложения VB.NET, используя Microsoft.Practices.EnterpriseLibrary.Data. Database.ExecuteReader () , возвращающий System.Data. IDataReader и следующая функция для преобразования IDataReader в DataSet.

    Public Shared Function ConvertIDataReaderToDataSet(ByVal reader As IDataReader) As DataSet
        Dim schemaTable As DataTable = reader.GetSchemaTable()
        Dim dataTable As DataTable = New DataTable

        For intCounter As Integer = 0 To schemaTable.Rows.Count - 1
            Dim dataRow As DataRow = schemaTable.Rows(intCounter)
            Dim columnName As String = CType(dataRow("ColumnName"), String)
            Dim column As DataColumn = New DataColumn(columnName, CType(dataRow("DataType"), Type))
            dataTable.Columns.Add(column)
        Next

        Dim dataSet As DataSet = New DataSet
        dataSet.Tables.Add(dataTable)

        'dataSet.Load(reader, LoadOption.OverwriteChanges, dataTable) ' DEBUG
        While reader.Read()
            Dim dataRow As DataRow = dataTable.NewRow()
            For intCounter As Integer = 0 To reader.FieldCount - 1
                dataRow(intCounter) = reader.GetValue(intCounter)
            Next
            dataTable.Rows.Add(dataRow)
        End While

        Return dataSet
    End Function

Отладка и пошаговое выполнение этой функции заканчивается строкой «While reader.Read ()».Также пробовал другую версию, используя DataSet.Load (), но с тем же результатом.

Нашел этот поток на MSDN , где другие с такой же проблемой, похоже, решили его, настроив свои запросы, добавивindexes.

Как я могу продолжить исследование проблемы, когда кажется, что процедура работает (отвечает в течение ~ 100 - 200 мс) и IDataReader.Read () просто заканчивается (или продолжает работать в фоновом режиме?)

  • Могу ли я рассчитать время процедуры другим (лучшим) способом?
  • Могут ли быть какие-либо блокировки таблицы или транзакции?

Все советы очень важны :)

1 Ответ

0 голосов
/ 21 сентября 2011

Ваш тест в SQL Developer просто измеряет время, необходимое для открытия курсора.Открытие курсора не приводит к тому, что Oracle фактически выполняет запрос - это не происходит до тех пор, пока вы не получите данные из курсора, и каждый раз, когда вы выбираете, Oracle будет продолжать обрабатывать запрос, чтобы получить следующий набор строк.В общем случае Oracle не нужно выполнять весь запрос в любой момент времени.Чтобы быть сопоставимым тестом, ваш блок PL / SQL должен был бы извлечь все данные из курсора.Что-то вроде

DECLARE
  CUR_OUT UTILS.T_CURSOR;
  P_ARTTYID NUMBER;
  P_ORDERST VARCHAR2(200);
  P_DRUMNO VARCHAR2(200);
  P_SHIPPINGNO VARCHAR2(200);
  P_DELIVERYDATEFROM DATE;
BEGIN
  P_ARTTYID := 2;
  P_ORDERST := '3';
  P_DRUMNO := '611-480';
  P_SHIPPINGNO := NULL;
  P_DELIVERYDATEFROM := '2005-01-01';

  C_T_ORDER_GETOVERVIEW(
    CUR_OUT => CUR_OUT,
    P_ARTTYID => P_ARTTYID,
    P_ORDERST => P_ORDERST,
    P_DRUMNO => P_DRUMNO,
    P_SHIPPINGNO => P_SHIPPINGNO,
    P_DELIVERYDATEFROM => P_DELIVERYDATEFROM
  );

  LOOP
    FETCH cur_out
     INTO <<list of variables to fetch data into>>;

    EXIT WHEN cur_out%notfound;
  END LOOP;

  --DBMS_OUTPUT.PUT_LINE('CUR_OUT = ' || CUR_OUT); -- Doesn´t work ;|
END;

Вы говорите, что в вашем .Net коде строка reader.Read() никогда не возвращается?Или вы говорите, что ваш код прерывается в этот момент?

...