МН Oracle / SQL - Является Исключениями NO_DATA_FOUND плохо для производительности хранимой процедуры?

Используя график рассеяния, вы можете получить доступ к параметру style (или даже size). Но вы можете не закончить с вашим предполагаемым макетом в конце. документация по точечной диаграмме .

Или вы можете использовать catplot и играть со строками и столбцами. Seaborn Doc для Catplot

К сожалению, Seaborn не обеспечивает изначально то, что вы ищете: еще один уровень вложенности, кроме параметра hue в stripplot (см. документация Stripplot [ 117]. Открыты некоторые билеты на морское побережье, которые могут быть связаны, например, этот билет . Но я пришел по некоторым подобным запросам функций в морском вокзале, которые были отклонены, см. этот билет

]

Последняя возможность - погрузиться в примитивы matplotlib, чтобы манипулировать вашей диаграммой морского происхождения (так как морская волна находится только на вершине matplotlib). Само собой разумеется, что это потребует больших усилий и может привести к аннулированию морского происхождения первое место;)

25
задан AJ. 21 October 2008 в 14:05
поделиться

10 ответов

Я не использовал бы явный курсор, чтобы сделать это. Steve F. больше не советует людям использовать явные курсоры, когда неявный курсор мог использоваться.

метод с count(*) небезопасен. Если другая сессия удаляет строку, которая удовлетворила условию после того, как строка с эти count(*), и перед строкой с эти select ... into, код выдаст исключение, которое не будет обработано.

вторая версия из исходного сообщения не имеет этой проблемы, и это обычно предпочитается.

Однако существует незначительное служебное использование исключения, и если Вы на 100% уверены, что данные не изменятся, можно использовать эти count(*), но я рекомендую против него.

я выполнил эти сравнительные тесты на [1 112] Oracle 10.2.0.1 на [1 113] Windows на 32 бита. Я только смотрю на прошедшее время. Существуют другие тестовые обвязки, которые могут предоставить больше подробную информацию (такую как количества фиксатора и используемая память).

SQL>create table t (NEEDED_FIELD number, COND number);

Таблица составлена.

SQL>insert into t (NEEDED_FIELD, cond) values (1, 0);

1 строка создается.

declare
  otherVar  number;
  cnt number;
begin
  for i in 1 .. 50000 loop
     select count(*) into cnt from t where cond = 1;

     if (cnt = 1) then
       select NEEDED_FIELD INTO otherVar from t where cond = 1;
     else
       otherVar := 0;
     end if;
   end loop;
end;
/

процедура пуазейли / процедура SQL, успешно завершенная.

Истекший: 0:00:02.70

declare
  otherVar  number;
begin
  for i in 1 .. 50000 loop
     begin
       select NEEDED_FIELD INTO otherVar from t where cond = 1;
     exception
       when no_data_found then
         otherVar := 0;
     end;
   end loop;
end;
/

процедура пуазейли / процедура SQL, успешно завершенная.

Истекший: 0:00:03.06

32
ответ дан 28 November 2019 в 20:36
поделиться

Так как ВЫБОР В предполагает, что единственная строка будет возвращена, можно использовать оператор формы:

SELECT MAX(column)
  INTO var
  FROM table
 WHERE conditions;

IF var IS NOT NULL
THEN ...

ВЫБОР даст Вам значение, если Вы будете доступны, и значение ПУСТОГО УКАЗАТЕЛЯ вместо исключения NO_DATA_FOUND. Издержки, представленные МАКСОМ (), будут минимальны к нулю, так как набор результатов содержит единственную строку. Это также имеет преимущество того, чтобы быть компактным относительно основанного на курсоре решения и не быть уязвимым для проблем параллелизма как двухступенчатое решение в исходном сообщении.

7
ответ дан 28 November 2019 в 20:36
поделиться

Альтернатива коду @Steve.

DECLARE
  CURSOR foo_cur IS 
    SELECT NEEDED_FIELD WHERE condition ;
BEGIN
  FOR foo_rec IN foo_cur LOOP
     ...
  END LOOP;
EXCEPTION
  WHEN OTHERS THEN
    RAISE;
END ;

цикл не выполняется, при отсутствии данных. Курсор ДЛЯ циклов является способом пойти - они помогают избежать большого обслуживания. Еще более компактное решение:

DECLARE
BEGIN
  FOR foo_rec IN (SELECT NEEDED_FIELD WHERE condition) LOOP
     ...
  END LOOP;
EXCEPTION
  WHEN OTHERS THEN
    RAISE;
END ;

, Который работает, если Вы знаете полный избранный оператор во время компиляции.

6
ответ дан 28 November 2019 в 20:36
поделиться

@DCookie

я просто хочу указать, что можно бросить строки, которые говорят

EXCEPTION  
  WHEN OTHERS THEN    
    RAISE;

, Вы получите тот же эффект, если Вы бросите блок исключения все вместе, и номер строки, о котором сообщают для исключения, будет строкой, где исключение на самом деле выдается, не строка в блоке исключения, где это было повторно повышено.

4
ответ дан 28 November 2019 в 20:36
поделиться

Stephen Darlington делает очень правильное замечание, и Вы видите что при изменении моего сравнительного теста для использования более реалистично размерной таблицы, если я заполняю таблицу к 10 000 строк с помощью следующего:

begin 
  for i in 2 .. 10000 loop
    insert into t (NEEDED_FIELD, cond) values (i, 10);
  end loop;
end;

Тогда повторно выполняет сравнительные тесты. (Я должен был уменьшить количества цикла до 5 000 для получения соответствующего времени).

declare
  otherVar  number;
  cnt number;
begin
  for i in 1 .. 5000 loop
     select count(*) into cnt from t where cond = 0;

     if (cnt = 1) then
       select NEEDED_FIELD INTO otherVar from t where cond = 0;
     else
       otherVar := 0;
     end if;
   end loop;
end;
/

PL/SQL procedure successfully completed.

Elapsed: 00:00:04.34

declare
  otherVar  number;
begin
  for i in 1 .. 5000 loop
     begin
       select NEEDED_FIELD INTO otherVar from t where cond = 0;
     exception
       when no_data_found then
         otherVar := 0;
     end;
   end loop;
end;
/

PL/SQL procedure successfully completed.

Elapsed: 00:00:02.10

метод за исключением теперь более двух раз как быстро. Так, почти для всех случаев, метода:

SELECT NEEDED_FIELD INTO var WHERE condition;
EXCEPTION
WHEN NO_DATA_FOUND....

способ пойти. Это даст корректные результаты и является обычно самым быстрым.

3
ответ дан 28 November 2019 в 20:36
поделиться

Если важно, чтобы Вы действительно сравнили обеих опций!

Однако я всегда использовал метод исключения, обоснование, являющееся, лучше только поразить базу данных однажды.

2
ответ дан 28 November 2019 в 20:36
поделиться

Да, Вы избегаете использовать курсоры

DECLARE
  CURSOR foo_cur IS 
    SELECT NEEDED_FIELD WHERE condition ;
BEGIN
  OPEN foo_cur;
  FETCH foo_cur INTO foo_rec;
  IF foo_cur%FOUND THEN
     ...
  END IF;
  CLOSE foo_cur;
EXCEPTION
  WHEN OTHERS THEN
    CLOSE foo_cur;
    RAISE;
END ;

по общему признанию, это - больше кода, но он не использует ИСКЛЮЧЕНИЯ в качестве управления потоком, которому, изучив большинство моих МН / SQL из МН книги Программирования Steve Feuerstein / книги Программирования SQL, я верю, чтобы быть хорошей вещью.

, Быстрее ли это или не, я не знаю (я делаю очень мало МН / SQL в наше время).

1
ответ дан 28 November 2019 в 20:36
поделиться

Вместо того, что вложил курсор циклично выполняется, более эффективный подход должен был бы использовать один цикл курсора с внешним объединением между таблицами.

BEGIN
    FOR rec IN (SELECT a.needed_field,b.other_field
                  FROM table1 a
                  LEFT OUTER JOIN table2 b
                    ON a.needed_field = b.condition_field
                 WHERE a.column = ???)
    LOOP
       IF rec.other_field IS NOT NULL THEN
         -- whatever processing needs to be done to other_field
       END IF;
    END LOOP;
END;
1
ответ дан 28 November 2019 в 20:36
поделиться

Вы не должны использовать открытый, когда Вы используете для циклов.

declare
cursor cur_name is  select * from emp;
begin
for cur_rec in cur_name Loop
    dbms_output.put_line(cur_rec.ename);
end loop;
End ;

или

declare
cursor cur_name is  select * from emp;
cur_rec emp%rowtype;
begin
Open cur_name;
Loop
Fetch cur_name into  Cur_rec;
   Exit when cur_name%notfound;
    dbms_output.put_line(cur_rec.ename);
end loop;
Close cur_name;
End ;
0
ответ дан 28 November 2019 в 20:36
поделиться

Может бить мертвую лошадь здесь, но я сравнил курсора для цикла, и это работало о, а также no_data_found метод:

declare
  otherVar  number;
begin
  for i in 1 .. 5000 loop
     begin
       for foo_rec in (select NEEDED_FIELD from t where cond = 0) loop
         otherVar := foo_rec.NEEDED_FIELD;
       end loop;
       otherVar := 0;
     end;
   end loop;
end;

процедура пуазейли / процедура SQL, успешно завершенная.

Истекший: 0:00:02.18

0
ответ дан 28 November 2019 в 20:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: