NULL 열을 NOT NULL로 빠르게 변경


11

수백만 행의 테이블과 NULL 값을 허용하는 열이 있습니다. 그러나 현재 해당 열에 대해 NULL 값을 가진 행이 없습니다 (쿼리로 상당히 빨리 확인할 수 있습니다). 그러나 내가 명령을 실행할 때

ALTER TABLE MyTable ALTER COLUMN MyColumn BIGINT NOT NULL;

쿼리가 걸립니다 영원히 상대적으로 말하기. 실제로 검사 제한 조건을 추가하는 것보다 두 배 이상 걸리는 시간은 실제로 10 분에서 20 분 사이입니다. 특히 해당 열에 대해 NULL 값을 가진 행이 없다는 것을 알고 있기 때문에 해당 열에 대한 테이블의 메타 데이터를 즉시 업데이트하는 방법이 있습니까?


2
아니요 (또는 적어도 문서화 된 / 지원되는 방법을 사용하지 않음). ALTER COLUMN to NOT NULL이 대량 로그 파일 증가를 유발하는 이유는 무엇입니까?를
Martin Smith

2
Sch-M"영원히"필요할 때 잠금을 기다리고있을 수도 있습니다 . 대기 중이거나 바쁜지 확인 했습니까?
Martin Smith

@MartinSmith 나는 내가 영원히 의미하는 바를 분명히했다 . 다른 세션이 데이터베이스에 충돌하지 않는 개발 환경에서 이것을 테스트하고 있습니다. 결국 완료됩니다. 그러나 당신이 연결 한 답변은 왜 그렇게 오래 걸리는지를 설명합니다. 귀하의 의견을 답변으로 바꾸어 줄 수 있다면, 나는 그것을 받아 들일 것입니다.
Joseph Daigle

답변:


12

@ypercube의 답변 은 메타 데이터 전용 변경으로 이것을 부분적으로 관리합니다.

제약 조건을 추가 NOCHECK한다는 것은 행을 읽을 필요가 없다는 것을 의미하며 열에 NULL값이 포함되지 않은 위치에서 시작하는 경우 (그리고 제약 조건을 확인하고 추가하는 사이에 아무것도 추가되지 않는 경우) 제약 조건으로 인해 NULL미래 INSERT또는 UPDATE작업 에서 값이 생성되지 않으므로 작동합니다.

그러나 제약 조건을 추가하면 동시 트랜잭션에 여전히 영향을 줄 수 있습니다. 는 ALTER TABLE취득해야합니다 Sch-M먼저 잠금을. 이를 기다리는 동안 다른 모든 테이블 액세스는 여기에 설명대로 차단 됩니다 .

그러나 일단 Sch-M잠금이 획득되면 작업이 매우 빨라야합니다.

이것의 한 가지 문제점은 실제로 컬럼에 NULLs 가 없다는 것을 알고 있더라도 쿼리 최적화 프로그램이 제한 조건을 신뢰하지 않으므로 계획이 최적이 아님을 의미합니다.

CREATE TABLE T (X INT NULL)

INSERT INTO T 
SELECT ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values

ALTER TABLE T WITH NOCHECK
  ADD  CONSTRAINT X_NOT_NULL 
    CHECK (X IS NOT NULL) ; 

SELECT *
FROM T 
WHERE X NOT IN (SELECT X FROM T)

계획

이것을 더 간단한 것과 비교하십시오

ALTER TABLE T ALTER COLUMN X INT NOT NULL

SELECT *
FROM T 
WHERE X NOT IN (SELECT X FROM T)

계획

이 방법으로 열 정의를 변경하면 발생할 수있는 한 가지 문제점은 모든 행을 읽어서 조건을 충족하는지 확인해야 할뿐만 아니라 실제로 행에 대한 로그 업데이트를 수행 할 수 있다는 것 입니다.

가능한 절반 방법은 점검 제한 조건을 추가하는 것 WITH CHECK입니다. WITH NOCHECK모든 행을 읽어야하는 것 보다 속도가 느리지 만 쿼리 최적화 프로그램이 위의 쿼리에서 더 간단한 계획을 제공 할 수 있으므로 기록 된 업데이트 문제가 발생하지 않아야합니다.


7

열을 변경하는 대신 옵션으로 테이블 CHECK제약 조건을 추가 할 수 NOCHECK있습니다.

ALTER TABLE MyTable WITH NOCHECK
  ADD  CONSTRAINT MyColumn_NOT_NULL 
    CHECK (MyColumn IS NOT NULL) ;

1
이렇게하면 열을 NULL만들지 만 쿼리 최적화 프로그램에서 사용할 수없는 향후 업데이트 나 삽입을 방지 할 수 있습니다.
Martin Smith

@MartinSmith 예, 비슷한 질문에 대한 답변과 의견을 읽었습니다. SQL Server의 큰 테이블에 NOT NULL 열을 어떻게 추가합니까? 문제 또는 더 나은 해결책에 대한 답변을 추가하고 제거하겠습니다.
ypercubeᵀᴹ

2
더 나은 해결책이 없습니다. 부분 솔루션을 제공하기 때문에 이것을 올렸습니다. 모든 영업 이익은하고 싶어하면 IS는 작동합니다 (빠르게보다해야 유효하지 않은 데이터 방지 ALTER COLUMN한 번으로 Sch-M잠금이 획득이 전혀 행을 스캔해야하지 않습니다). 그것은 동일하지 않다는 것을 지적하는 것입니다 (예를 들어 NOT IN쿼리에서 사용된다면 계획은 더 복잡 할 것입니다)
Martin Smith
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.