MSSQL2005 부터 생긴 Cross Apply 조인


아직 많은 테스트가 필요하지만 적당한 Index가 있을 경우 처리할 데이터를 상당히 줄여줘 성능 향상에 도움이 된다

(다른 경우도 마찬가지지만 더욱 큰 폭으로)

특히 해당 유저의 최근 기록 같은 류의 정보를 추출할 때 기존 방식의 경우 이를 다시  Self Join 하거나 

문자열 조작으로 처리하곤 했는데 

Self Join 의 경우 테이블을 두번 읽게 되고 문자열 조작의 경우 그 구문이 상당히 길어질 뿐더러 복잡해서 쉽게 사용 하기 힘들다

더군다나 SQL의 경우 (C, C++, C#, Java, 등등의)프로그램 랭귀지들 보다 문자열 처리에 느린 편이다


하지만 Cross Apply의 경우 비교적 간단한 구문으로 빠르고 유용하게 사용 할 수 있다

이는 유지보수도 쉬워서 내가 아닌 다른 사람이 주석 없이도 내용 파악이 쉽고 그만큼 실수를 할 가능성도 줄어듬을 의미한다.


조심할 점은 Nested Loop Join으로 풀어 나가니 대용량 처리에는 부적합 하고 이런 저런 테스트를 꼭 해봐야 한다는 것!


--기존방식
SELECT a.UID, b.RegDate
FROM dbo.[User] AS a WITH(NOLOCK)
INNER JOIN
(
	SELECT a.UID, MAX(a.RegDate) AS RegDate
	FROM dbo.[UserLoginLog] AS a WITH(NOLOCK)
	GROUP BY a.UID
) AS b ON a.UID = b.UID


--Cross Apply
SELECT a.UID, b.RegDate
FROM dbo.[User] AS a WITH(NOLOCK)
CROSS APPLY
(
	SELECT TOP 1 b.UID, b.RegDate
	FROM dbo.[UserLoginLog] AS b WITH(NOLOCK)
	WHERE a.UID = b.UID
	ORDER BY RegDate DESC
) AS b
위의 실행 결과 비교는 다음과 같다


테스트용 데이터 이기 때문에 데이터 량이 적지만 실제 서버의 엄청난 데이터를 생각한다면 그 차이는 더더욱 클 것이라 생각된다.



ps1. Apply 구문에는 Cross Apply와 Outer Apply가 존재 하며
       이 차이는 Inner Join과 Left Outer Join혹은 Right Outer Join과 동일함

ps2. 테스트 데이터는 다음과 같이 만들었음
CREATE DATABASE TEST;
GO

USE TEST;
GO

CREATE TABLE dbo.[User]
(
	 UID int
	,Name varchar(10)

	,CONSTRAINT PK_User_UID PRIMARY KEY(UID)
);


CREATE TABLE dbo.[UserLoginLog]
(
	 UID int
	,RegDate datetime

	,CONSTRAINT FK_UserLoginLog_User_UID FOREIGN KEY(UID) REFERENCES dbo.[User](UID)
);

CREATE UNIQUE CLUSTERED INDEX UIDX_UserLoginLog_UID_RegDate ON dbo.[UserLoginLog](UID, RegDate);
GO

INSERT INTO dbo.[User](UID, Name) VALUES(1, '가나다');
INSERT INTO dbo.[User](UID, Name) VALUES(2, '라마바');
INSERT INTO dbo.[User](UID, Name) VALUES(3, '사아자');
INSERT INTO dbo.[User](UID, Name) VALUES(4, '차카타');
GO


INSERT INTO dbo.[UserLoginLog](UID, RegDate)
SELECT ROW_NUMBER() OVER(ORDER BY a.OBJECT_ID) % 4 + 1 AS UID, DATEADD(SS,  ROW_NUMBER() OVER(ORDER BY a.OBJECT_ID), GETDATE()) AS RegDate
FROM sys.objects AS a
	CROSS JOIN sys.objects AS b;
GO



Posted by Mr.Jo :