programing

Oracle 삭제 쿼리에 시간이 너무 많이 걸림

megabox 2023. 7. 13. 20:48
반응형

Oracle 삭제 쿼리에 시간이 너무 많이 걸림

다음과 같은 질문이 있습니다.

DELETE from tablename where colname = value;

실행하는 데 엄청나게 오랜 시간이 걸립니다.그 이유는 무엇일까요?콜네임에 대한 색인이 있습니다.

쿼리에 시간이 오래 걸리는 이유에는 다음과 같은 여러 가지 설명이 있을 수 있습니다.

  1. 다른 세션에 의해 차단될 수 있습니다(가능성이 높습니다.에 다른 해야 합니다.를 들어 issue 삭제기전하예행사잠않을확았합지니인야다해는그지용가자른다에예▁issue)▁before합(니다,▁you확야인:▁eg해▁make▁is▁rows▁should▁the: issue)SELECT NULL FROM tablename WHERE colname=:value FOR UPDATE NOWAIT,
  2. ▁be▁a다가 있을 수 .ON DELETE TRIGGER일을 , 것은추일합그다니을인.
  3. 있는지 확인합니다.UNINDEXED REFERENCE CONSTRAINTS이 테이블을 가리킵니다(색인되지 않은 외부 키가 있는지 확인하는 데 도움이 되는 AskTom의 스크립트가 있습니다).

테이블이 여러 테이블과 관련되어 있을 경우 행 수가 많을 수 있습니다.

그 지수는 얼마나 선별적입니까?테이블에 백만 개의 행이 있고 그 값이 15만 개의 행에 도달하면 인덱스는 쓸모가 없습니다.사실 그것이 실제로 사용되고 있다면 쓸모없는 것보다 더 나쁠 수도 있습니다.DELETE는 SELECT 문과 같습니다. 액세스 경로를 조정할 수 있습니다.

또한 삭제는 실행 취소 테이블 공간을 많이 차지하므로 시스템을 많이 사용하는 경우 경합이 발생할 수 있습니다.다중 사용자 시스템에서 다른 세션에 삭제할 행이 잠겨 있을 수 있습니다.

ON DELETE 트리거가 있습니까?ON DELETE 캐스케이드 외래 키 제약 조건이 있습니까?

편집: 모든 내용, 특히 문제의 열이 기본 키이기 때문에 단일 행을 삭제하려는 경우 시간이 오래 걸리는 경우 다른 프로세스나 사용자가 행을 잠글 가능성이 높습니다.안에 뭐가 있나요?V$LOCK?

그래서 저는 제 경험을 올리겠습니다.누군가에게 도움이 될 수도 있습니다.

쿼리

delete from foo
where foo_id not in ( 
  select max(foo_id) from foo group by foo_bar_id, foo_qux_id
);

16에 총의 레코드를 삭제하는가 걸렸습니다. 표에 있는 총 2300개의 레코드에서 1700개의 레코드를 삭제했습니다.foo.

저는 다른 답변과 같이 외부 키의 인덱스를 모두 확인했습니다.그것은 도움이 되지 않았습니다.

솔루션:

쿼리를 다음으로 변경했습니다.

delete from foo
where foo_id in ( 
  select foo_id from foo
  minus
  select max(foo_id) from foo group by foo_bar_id, foo_qux_id
);

ㅠㅠㅠㅠnot inin 및사된을 했습니다.minus정확한 결과를 얻기 위해.

이제 쿼리가 0.04초 안에 실행됩니다.

도움이 된다면 제 경험을 게시하는 것입니다.

저도 같은 문제(삭제 또는 업데이트 시간이 길기 때문에 '고정' 쿼리를 찾아 죽이는 것이 본능적인 반응이었습니다.하지만 그것들을 찾기 위한 제 정상적인 SQL은 아무것도 보여주지 않았습니다.조금 파고든 후, 저는 대신 '잠긴 테이블'을 찾았고, 제가 바꾸려는 테이블을 적극적으로 차단하고 있는 것처럼 보이는 비활성 세션을 찾을 수 있었습니다.다음은 테이블 업데이트를 차단하는 세션을 찾기 위해 사용한 쿼리(Oracle 12c)입니다.

SELECT
   c.owner,
   c.object_name,
   c.object_type,
   b.sid,
   b.serial#,
   b.status,
   b.osuser,
   b.machine
FROM
   v$locked_object a ,
   v$session b,
   dba_objects c
WHERE
   b.sid = a.session_id
AND
   a.object_id = c.object_id;

그런 다음 sid 및 위 쿼리의 serial#을 사용합니다.

ALTER SYSTEM KILL SESSION 'SID, SERIAL#' to end those sessions and free the locks.

저는 dba가 아닙니다. 나쁜 관행일 수도 있지만, 저에게는 효과가 있었습니다.

당신의 테이블에는 더 많은 레코드가 있습니까?
데이터베이스 서버에서 실행 중인 재귀 프로그램(일부 중첩 루프 등)이 있습니까?
데이터베이스 서버가 다른 컴퓨터에 있는 경우 네트워크 문제를 확인하시겠습니까?

Oracle과 mysql 사이에는 상당한 차이가 있습니다.

Oracle은 외부 키에 대한 인덱스를 자동으로 생성하지 않지만 mysql은 자동으로 생성합니다.그런 다음 delete 명령을 실행할 수 있는 상위 테이블이 있는 경우 하위 테이블의 외부 키에 인덱스를 만들어야 합니다. 그렇지 않으면 하위 테이블에 행이 많을 경우 상위 테이블의 delete 명령은 상위 레코드 삭제 시 하위 테이블의 모든 레코드를 검색해야 하므로 매우 느려집니다.

그런 다음 Oracle 데이터베이스의 상위 테이블에서 삭제할 때 주의하십시오.

언급URL : https://stackoverflow.com/questions/1327190/oracle-delete-query-taking-too-much-time

반응형