IT

PL/SQL에서 커서를 루프하는 FETCH/FOR 간의 차이

itgroup 2023. 7. 7. 18:56
반응형

PL/SQL에서 커서를 루프하는 FETCH/FOR 간의 차이

커서를 가져오면 %ROWCOUNT, %ROWTYPE, %Found, %NOTFOUND, %ISOPEN과 같은 변수에 액세스할 수 있습니다.

...하지만 다른 이유가 있는지 궁금해서요

열기 - 가져오기 - 명령을 닫으면 커서가 루프됩니다.

보다는

FOR 사이클로 커서 루프...(단순하기 때문에 더 좋다고 생각합니다.)

당신은 어떻게 생각하나요?

성능 측면에서 볼 때, OMG Ponys가 링크한 팀 홀 보다 훨씬 더 복잡합니다.저는 이 팁이 웹에서 발췌한 더 큰 섹션에 대한 소개라고 생각합니다. 저는 팀이 책에서 이 모든 것이 아니더라도 대부분의 요점을 계속해서 만들 것이라고 기대합니다.또한 이 전체 논의는 사용 중인 Oracle 버전에 따라 달라집니다.이것이 10.2, 11.1 및 11.2에 대해서는 정확하다고 생각하지만 이전 릴리스로 돌아가면 분명히 차이가 있습니다.

먼저, 팁의 특정 예는 다소 비현실적입니다.SELECT INTO가 아닌 명시적 커서를 사용하여 단일 행 가져오기를 코딩하는 사람을 본 적이 없습니다.따라서 SELECT INTO가 더 효율적이라는 사실은 실질적으로 매우 제한적입니다.루프에 대해 논의하고 있다면, 우리가 관심을 갖는 성능은 많은 행을 가져오는 데 얼마나 많은 비용이 드는가 하는 것입니다.바로 여기서 복잡성이 나타나기 시작합니다.

Oracle은 10.1에서 커서에서 PL/SQL 컬렉션으로 대량의 데이터를 수집하는 기능을 도입했습니다.이렇게 하면 한 번에 여러 행을 가져와 컨텍스트 이동을 최소화할 수 있기 때문에 SQL 엔진에서 PL/SQL 컬렉션으로 데이터를 가져오는 훨씬 효율적인 방법입니다.코드가 PL/SQL 엔진 내에 유지될 수 있기 때문에 이러한 컬렉션에 대한 후속 작업이 더 효율적입니다.

그러나 BULK COLLECT 구문을 최대한 활용하려면 일반적으로 명시적 커서를 사용해야 합니다. 이렇게 하면 PL/SQL 컬렉션을 채울 수 있고 이후 FORALL 구문을 사용하여 데이터를 데이터베이스에 다시 쓸 수 있기 때문입니다(커서에 데이터 묶음을 가져오는 경우에는일종의 조작을 수행하고 조작된 데이터를 어딘가에 저장하고 있을 가능성이 높습니다.)OMG Ponys가 올바르게 지적한 것처럼 FOR 루프에서 암시적 커서를 사용하는 경우 Oracle은 데이터 가져오기 비용을 줄이기 위해 백그라운드에서 대량 수집을 수행합니다.그러나 데이터가 컬렉션에 없기 때문에 코드가 행별 삽입 및 업데이트 속도가 느려집니다.명시적 커서는 또한 FOR 루프의 암시적 커서에 대해 기본값인 100보다 성능을 향상시킬 수 있는 LIMIT를 명시적으로 설정할 수 있는 기회를 제공합니다.

일반적으로, 당신이 10.2 이상이고 당신의 코드가 데이터를 가져와서 데이터베이스에 다시 쓰고 있다고 가정하면,

가장 빠른

  1. BULK COLLECT를 로컬 컬렉션에 수행하고(적절한 제한 포함) FORALL을 사용하여 데이터베이스에 다시 쓰는 명시적 커서.
  2. 암시적 커서를 사용하여 배경 뒤에서 BULK COLLECT를 수행하고 단일 행으로 데이터베이스에 다시 기록합니다.
  3. BULK COLLECT를 수행하지 않고 PL/SQL 수집을 활용하지 않는 명시적 커서.

가장 느림

반면에 암시적 커서를 사용하면 이전 코드를 리팩터링하거나 새 기능을 학습하는 데 드는 초기 비용을 거의 사용하지 않고 대량 작업을 사용할 수 있습니다.PL/SQL 개발의 대부분이 기본 언어가 다른 것이거나 반드시 새로운 언어 기능을 따라가지 않는 개발자들에 의해 수행된다면, FOR 루프는 모든 새로운 BULK COLLECT 기능을 사용했던 명시적인 커서 코드보다 이해하고 유지하기가 더 쉬울 것입니다.또한 Oracle이 향후 새로운 최적화를 도입할 경우 명시적 코드를 수동으로 재작업해야 하는 반면 암시적 커서 코드는 자동으로 이점을 얻을 가능성이 훨씬 높습니다.

물론 성능 문제를 해결할 때 루프 코드의 다양한 변형이 얼마나 빠를지에 대해 정말로 관심을 가질 때쯤에는 더 많은 논리를 순수 SQL로 이동하고 루프 코드를 완전히 버리는 것을 고려해야 할 때가 많습니다.

OPEN / FETCH / CLOSE는 명시적 커서 구문이라고 하며 후자는 암시적 커서 구문이라고 합니다.

이미 알고 있는 한 가지 주요 차이점은 암시적 커서에서 %Found/%NOT FOUND/ 등을 사용할 수 없다는 것입니다.또 다른 주의할 점은 암시적 커서가 명시적 커서보다 빠르다는 것입니다. 명시적 논리를 지원하지 않을 뿐만 아니라 사전(~100개의 레코드?)을 읽습니다.

추가 정보:

저는 이 두 가지 인식에서 한 가지 외에 어떤 결정적인 차이도 모릅니다.for ... loop후, 루프가 종료된 경우에는 .open ... fetch ... close구문은 커서를 직접 닫는 것이 좋습니다(좋은 방법일 뿐입니다). 이것이 필요하지 않다고 생각했습니다.Oracle은 가시성 범위를 자동으로 아웃바운드로 커서를 닫습니다.또한 사용할 수 없습니다.%FOUND그리고.%NOTFOUNDfor ... loop커서

나로서는, 나는 그것을 발견합니다.for ... loop훨씬 더 쉽게 읽고 지원할 수 있습니다.

제가 틀렸다면 고쳐주세요. 하지만 저는 두 가지 모두 다른 것에는 없는 좋은 점이 있다고 생각합니다.

루프의 경우 다음과 같이 수행할 수 있습니다.

for i in (select * from dual)
  dbms_output.put_line('ffffuuu');
end loop;

그리고 열린 채로..fetch 당신은 이렇게 할 수 있습니다:

declare
  cur sys_refcursor;
  tmp dual.dummy%type;
begin
  open cur for 'select dummy from dual';
  loop
    fetch cur into tmp;
    exit when cur%notfound;
    dbms_output.put_line('ffffuuu');
  end loop;
  close cur;
end;

따라서 개방형 페치에서는 동적 커서를 사용할 수 있지만 루프에서는 선언 없이 일반 커서를 정의할 수 있습니다.

언급URL : https://stackoverflow.com/questions/3885469/difference-between-fetch-for-to-loop-a-cursor-in-pl-sql

반응형