테이블을 크게 변경하는 것이 더 낫습니다. 매번 DELETE 및 INSERT 또는 기존 업데이트?


27

나는 매일 한 테이블에서 약 36K 레코드를 변경 해야하는 프로젝트를 만들고 있습니다. 나는 무엇을 더 잘할 것인지 궁금합니다.

  1. 행을 삭제하고 새 행을 삽입하거나
  2. 기존 행 업데이트

나를 위해 모든 행을 삭제하고 새 행을 삽입하는 것이 더 쉽지만 테이블과 인덱스를 조각화하고 성능에 영향을 줄 경우 가능한 경우 업데이트를 수행하고 필요할 때만 삭제 / 삽입을 선호합니다.

이것은 야간 서비스가 될 것이며 프로세스 자체의 속도를 향상시키지 않을 것입니다. 나는 일반적으로이 테이블에 대한 쿼리 성능에 대해 이미 8 억 9 천만 건의 레코드가 있고이 야간 프로세스가 어떻게 영향을 미치는지에 대해 더 우려하고 있습니다.

이 야간 프로세스에 대해 레코드를 삭제 / 삽입하거나 기존 레코드를 업데이트해야합니까 (가능한 경우)?


필드에 대한 인덱스의 존재 여부에 따라 테이블에 대한 자세한 내용을 제공해야한다고 생각합니다.
SRKX

답변:


9

실제로 변경되는 데이터 양에 따라 다릅니다. 이 테이블에 20 개의 열이 있다고 가정하겠습니다. 또한 각각 diff에 5 개의 색인이 있습니다. 기둥.

이제 20 개 열 모두의 값이 변경되거나 5 개 열의 데이터가 변경되고이 5 개 열이 모두 색인화 된 경우에도 "삭제 및 삽입"이 더 나을 수 있습니다. 그러나 2 개의 열만 변경되어 클러스터되지 않은 인덱스의 일부가 아니라고 말할 경우이 경우 클러스터 된 인덱스 만 업데이트되므로 인덱스를 업데이트하지 않는 것이 좋습니다. 업데이트).


추가 연구에서, SQL Server에는 내부적으로 UPDATE를 수행하기위한 두 가지 별도의 메커니즘이 있으므로 위의 의견은 중복되는 것으로 나타났습니다. - "현재 위치 업데이트"(예 : 원래 행에서 열 값을 새로운 것으로 변경) 또는 "제자리 비 업데이트"(DELETE 뒤에 INSERT).

적절한 업데이트가 규칙이며 가능한 경우 수행됩니다. 여기서 행은 같은 페이지에서 같은 범위에서 같은 위치에 정확하게 유지됩니다. 영향을받는 바이트 만 변경됩니다. tlog에는 하나의 레코드 만 있습니다 (업데이트 트리거가없는 경우). 힙이 업데이트되고 페이지에 충분한 공간이있는 경우 업데이트가 수행됩니다. 클러스터링 키가 변경되었지만 행을 전혀 이동할 필요가없는 경우에도 업데이트가 이루어집니다.

예를 들어,성에 클러스터형 인덱스가 있고 이름이 Able, Baker, Charlie 인 경우 Baker를 Becker로 업데이트하려고합니다. 행을 이동할 필요가 없습니다. 그래서 이것은 제자리에 걸릴 수 있습니다. 반면 Able을 Kumar로 업데이트해야하는 경우 행이 같은 페이지에 있더라도 행을 이동해야합니다. 이 경우 SQL Server는 DELETE와 INSERT를 차례로 수행합니다.

위의 사항을 고려하여 정상적인 업데이트를 수행하고 SQL Server가 내부적으로 수행하는 가장 좋은 방법을 찾도록 제안합니다.

"업데이트"내부 또는 SQL Server 관련 내부에 대한 자세한 내용은 Paul Randal 's 등의 Kalen Delaney 등의 SQL Server 2008 내부를 참조하십시오 .


8

SQL 2008에서 MERGE 명령 을 조사 했습니까 ? 기본 예는 다음과 같습니다.

  merge YourBigTable ybt
  using (select distinct (RecordID) from YourOtherTable) yot
     on yot.Recordid = YBT.RecordID
  when NOT matched by target
  then  insert (RecordID)
        values (yot.DeviceID) ;

이것은 기본적으로 "UPSERT"명령입니다. 존재하는 경우 업데이트하고없는 경우 삽입하십시오. 매우 빠르고 매우 멋진 명령입니다.


1
그것은 후드 아래의 동일한 역학 인 UPDATE보다 빠르지 않습니다.
Mark Storey-Smith

아직 존재하지 않는 것을 업데이트하고 삽입하는 것보다 빠릅니다.
datagod

2
그것이 사실이라면, 그것을 증명하십시오 :)
Mark Storey-Smith

4

그러나 필자는 3 천만 (3crore) 레코드가있는 테이블에서 삭제 및 삽입 대 업데이트를 확인했습니다. 이 테이블에는 하나의 클러스터 된 고유 복합 키와 3 개의 비 클러스터 키가 있습니다. 삭제 및 삽입의 경우 9 분이 걸렸습니다. 업데이트에는 55 분이 걸렸습니다. 각 행에서 하나의 열만 업데이트되었습니다.

그래서 나는 사람들에게 추측하지 말 것을 요청합니다. 열이 많고 데이터가 많은 큰 테이블을 다룰 때 수식이 변경됩니다.


또한이 사례를 수행했지만 때로는 소스 또는 대상, 힌트 또는 대상 하위 집합에 인덱스 (임시 또는 파마)를 추가하여 전체 병합을 최적화 할 수 있음을 발견했습니다 (전체 병합에는 적용되지 않음).
crokusek

3

업데이트가 빠르지 않습니다. 비결은 데이터를 삽입하는 동안 인덱스를 비활성화하는 것입니다.

이것을 사용하는 것을 고려하십시오 :

-- disable indexes
ALTER INDEX [index_name] ON dbo.import_table DISABLE
-- ... disable more indexes

-- don't use delete if you don't care about minimal logging. truncate is faster
TRUNCATE TABLE dbo.import_table

-- just insert the new rows
INSERT dbo.import_table
SELECT
    *
FROM
    dbo.source_table

-- rebuild indexes
ALTER INDEX [index_name] ON dbo.import_table REBUILD
-- ... rebuild more indexes

db 옵션에서 자동 통계 업데이트를 끄는 것도 더 빠릅니다. 테이블이 크게 변경된 경우 다음을 실행해야합니다.

UPDATE STATISTICS dbo.import_table

또는

EXEC sp_updatestats

통계를 최신 상태로 유지하기 위해 정기적으로 (DB 크기에 따라 매일, 매주) 작업으로 주목해야 할 것은 테이블이 비어있을 때 통계를 업데이트하는 것입니다. 테이블을 다시 채운 후에 통계를 실행하지 않으면 통계가 손상됩니다.


4
나는 이것이 항상 사실이라는 것에 동의하지 않는다. 또한 @adopilot의 질문에있는 테이블은 89m 레코드를 포함하고 36k 만 업데이트하려고하므로 TRUNCATE로 지울 수 없습니다.
Mark Storey-Smith

더 조심스럽게 게시물을 읽는 법을 배워야합니다! 나는 게시물을 업데이트 할 것이다 ... 실제로, 나는 많이 변경해야합니다.
Asken
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.