우리가 프로시져를 쓸 때 다음과 같은 구문을 자주 사용한다.
위의 구분은 업데이트 대상이 존재하는지 먼저 SELECT해 보고,IF ((SELECT COUNT(*) FROM TEST_TAB WHERE STATUS = 'S') > 0)
UPDATE TEST_TAB SET STATUS = 'R' WHERE STATUS = 'S'
대상이 있을 경우에만 UPDATE 한다는 뜻이다.
그렇다면, 왜 SELECT 테스트를 먼저 수행하는 것이 바로 UPDATE부터 수행하는 것보다 비용이 적을까?
(위의 예에서 테스트 대상 테이블은 26,000개의 레코드가 들어있었다.)
업데이트 대상이 존재할 경우, SELECT와 UPDATE를 둘 다 해야 하기 때문에
무조건 UPDATE부터 하는 것보다 분명히 더 비용이 비쌀 것으로 예상된다.
그렇다면... 업데이트 대상이 존재하지 않을 경우는 어떨까?
SELECT를 함으로서 UPDATE를 해보지 않아도 되기 때문에 더 적은 비용이 드는 걸까?
SELECT COUNT(*) FROM IP_TEST_TAB WHERE STATUS = 'S' -- 1
UPDATE TEST_TAB SET STATUS = 'R' WHERE STATUS = 'S' -- 2
STATUS 컬럼이 'S'인 레코드가 한개도 없는 (즉, 업데이트 대상이 0개인) 상황을 만들어 놓고 위의 두가지 해 보았다. 프로필러에 나타난 결과는 다음과 같다.
1번 SELECT 문 : CPU(235), READ(1761), WRITE(0), DURATION(236)
2번 UPDATE 문 : CPU(0), READ(1186), WRITE(0), DURATION(16)
즉, 대상 데이터가 한개도 없는 경우에도 바로 UPDATE부터 실행시키는 것이 훨씬 비용이 적다는 것이다.
그렇다면, SELECT를 해서 UPDATE할 데이터가 있는지 체크해보지 않고 직접 UPDATE부터 하는 것이 더 좋은 방법일까??
아래의 테스트를 해 보자.
-- 세션 1, 2에서 아래의 SQL을 순서대로 실행STATUS 컬럼을 모두 'R'로 변경한 상태에서 위의 SQL을 두 세션에서 순차적으로 실행시켜보자. 나중에 실행된 세션에서 LOCK이 걸리는가? 테스트해보면 LOCK이 걸리지는 않는 것을 알 수 있다.
BEGIN TRAN
UPDATE TEST_TAB SET STATUS = 'R' WHERE STATUS = 'S'
UPDATE문을 실행시킬 때는 EXCLUSIVE LOCK이 걸린다. 즉, UPDATE문은 동시에 두개가 실행될 수 없다는 뜻이다. 그런데, 위의 테스트를 통해 LOCK 이 걸리는 것은 실제 변경되는 RECORD가 발생할 때 부터라는 것을 알 수 있었다. 요약하면, "UPDATE문을 실행했더라도 WHERE에 의해 영향을 받는 ROWS가 없는 경우는 LOCK이 걸리지 않는다."
상기 테스트를 종합해 볼 때... 아래와 같은 결론을 내릴 수 있다.
1. 어떤 경우에도 업데이트 전에 SELECT 테스트를 수행하는 것이 비용이 더 비싸다.
2. SELECT 테스트 없이 직접 UPDATE를 날리더라도 변경 대상 레코드가 없는 경우에는 EXCLUSIVE LOCK이 걸리지 않는다.
※ 따라서 SELECT 테스트 없이 직접 UPDATE부터 날리는 것이 더 낫다.
'SQL Server' 카테고리의 다른 글
INSERT문 실행 후 INSERT된 IDENTITY를 확인하는 방법 (1) | 2008.08.15 |
---|---|
SQL Server의 SQL문에서 이벤트로그 기록하기 (0) | 2008.03.17 |
INSTEAD OF 트리거 (0) | 2008.03.17 |
SELECT에 LOCK을 거는 방법 (0) | 2008.03.17 |
SQL Server 프로시져 실행중 Sleep 주기 (0) | 2008.02.12 |