SQL Server 의 페이지 나 누 기 방식 ISNULL 과 COALESCE 성능 비교

머리말
지난 절 에 우 리 는 데이터 형식 과 문자열 중 몇 가지 주의해 야 할 부분 을 설명 했다.이 절 에서 우 리 는 문자열 의 줄 수 를 계속 이야기 하 는 동시에 다른 내용 과 삽 입 된 내용,짧 은 내용,깊이 있 는 설명 도 했다.문장 을 참고 할 수 있다SQL Server 의 데이터 형식 을 자세히 설명 합 니 다.)
페 이 징 방식
SQL 2005 나 SQL 2008 에서 저 희 는 ROW 를 이용 합 니 다.NUMBER 창 을 여 는 함수 로 페이지 를 나 눌 수 있 습 니 다.창 을 여 는 함수 에 대해 서 는 SQL 진급 에서 자세히 설명 하 겠 습 니 다.다음 과 같다.

USE TSQL2012
GO
DECLARE @StartRow INT
DECLARE @EndRow INT
SET @StartRow = 31
SET @EndRow = 40
SELECT [address], [city], [region]
FROM (
SELECT [SC].[address], [SC].[city], [SC].[region],
ROW_NUMBER() OVER(
ORDER BY [SC].[address], [SC].[city],[SC].[custid]) AS RowNumber
FROM Sales.Customers SC) SaleCustomer
WHERE RowNumber > @StartRow AND RowNumber < @EndRow
ORDER BY [address], [city], [region];
위의 코드 는 내 가 설명 할 필요 가 없 을 것 이 며,동시에 보 기 를 이용 하여 페이지 를 나 눌 수도 있다.

WITH SaleCustomer AS
(
SELECT [SC].[address], [SC].[city], [SC].[region],
ROW_NUMBER() OVER(
ORDER BY [SC].[address], [SC].[city],[SC].[custid]) AS RowNumber
FROM Sales.Customers SC)
SELECT [address], [city], [region]
FROM SaleCustomer
WHERE RowNumber > @StartRow AND RowNumber < @EndRow
ORDER BY [address], [city], [region]
GO
다음은 이 두 사람 이 SQL 검색 어 와 보 기 를 이용 하여 성능 상의 차이 가 있 는 지 살 펴 보 겠 습 니 다.자,검 사 는 바로.

여기 서 우 리 는 두 사람 이 성능 지출 에 있어 서 결코 다 르 지 않 고 대부분 상황 에서 똑 같 아야 한 다 는 것 을 알 수 있다.그러나 SQL 2011 이후 버 전에 새로운 문법 이 등장 하여 페이지 를 나 누 었 습 니 다.우 리 는 여전히 이용 하 는 ROW 일 것 입 니 다.NUMBER 는 SQL 버 전 을 2005 년 까지 호 환 할 수 있 도록 OFFSET-FETCH 를 이용 하여 필터 링 을 할 수 있 습 니 다.SQL 2011 을 기반 으로 한 것 입 니 다.상술 한 것 은 31 에서 40 사이 의 데 이 터 를 추출 하 는 것 입 니 다.만약 에 OFFSET-FETCH 로 이 루어 진다 면 우 리 는 이 함수 의 말 그대로 데 이 터 를 얼마나 건 너 뛰 고 얼마나 많은 데 이 터 를 캡 처 하 는 지 알 수 있 기 때문에 우 리 는 앞의 30 개의 데 이 터 를 건 너 뛰 고 다음 10 개의 데 이 터 를 취해 야 합 니 다.

USE TSQL2012
GO
DECLARE @PageSize INT = 10, @PageIndex INT = 3
SELECT *
FROM Sales.Customers
ORDER BY custid
OFFSET @PageIndex * @PageSize ROWS
FETCH NEXT 10 ROWS ONLY
GO
SQL 버 전에 대한 요구 가 낮 지 않다 면 OFFSET-FETCH 를 이용 해 시원 하 다.
COALESCE compare to ISNULL
지난 절 에 우 리 는 문자열 함 수 를 이 야 기 했 는데 그 중에서 문자열 함수 인 COALESCE 를 빠 뜨 렸 습 니 다.이 함 수 는 SQL 2008+에 있어 야 있 습 니 다.그 중에서 문자열 함수 에 대한 처리 와 유사 한 몇 가지 가 있 습 니 다.같이 살 펴 보 겠 습 니 다.msdn 은 변 수 를 순서대로 계산 하고 NULL 과 같 지 않 은 첫 번 째 표현 식 의 현재 값 을 되 돌려 줍 니 다.데이터 형식 우선 순위 가 가장 높 은 expression 의 데이터 형식 을 되 돌려 줍 니 다.모든 표현 식 이 Null 이 될 수 없다 면 결과 의 유형 도 Null 이 될 수 없습니다.모든 인자 가 NULL 이면 COALESCE 는 NULL 로 돌아 갑 니 다.최소한 하나의 Null 값 이 NULL 형식 이 어야 합 니 다.솔직히 NULL 에 대한 처리 야.우 리 는 간단하게 다음 예 를 보 자.

USE TSQL2012
GO
SELECT custid, country, region, city,
 country + COALESCE(N''+ region, N'') + N',' + city AS location
FROM Sales.Customers

위 에서 보 듯 이 우 리 는 COALESCE 함 수 를 통 해 NULL 을 빈 문자열 로 대체 합 니 다.SQL 2012 도 연결 할 입력 목록 을 받 아들 이 고 NULL 을 자동 으로 빈 문자열 로 대체 하 는 CONCAT 함 수 를 도 입 했 습 니 다.위 와 같이 CONCAT 함수 로 대체 할 수 있 습 니 다.

USE TSQL2012
GO
SELECT custid, country, region, city,
country + CONCAT(country,N''+ region, N',' + city) AS location
FROM Sales.Customers
동시에 다음 그림 을 보면 CONCAT 함수 매개 변 수 는 적어도 두 개가 있어 야 한 다 는 것 을 알 수 있 습 니 다.

msdn 은 CONCAT 함수 에 대해 다음 과 같이 설명 합 니 다.CONCAT 는 가 변 수량의 문자열 인 자 를 사용 하고 하나의 문자열 로 연결 합 니 다.그것 은 적어도 두 개의 입력 값 이 필요 하 다.그렇지 않 으 면 오류 가 발생 할 것 이다.모든 매개 변 수 는 문자열 형식 으로 암시 적 으로 변환 한 다음 연결 합 니 다.Null 값 이 빈 문자열 로 암시 적 으로 변 환 됩 니 다.모든 인자 가 Null 이면 varchar(1)형식의 빈 문자열 을 되 돌려 줍 니 다.암시 적 으로 문자열 로 변환 하 는 과정 은 기 존의 데이터 형식 변환 규칙 에 따른다. 
우 리 는 계속해서 COALESCE 함수 로 돌아 가 ISNULL 함수 와 의 차 이 를 살 펴 보 았 다.
COALESCE 와 ISNULL 함수 연구
어떤 사람들 은 ISNULL 이 COALESCE 함수 보다 빠르다 고 생각 하거나,ISNULL 과 COALESCE 함수 가 같다 고 생각 하거나,ANSI SQL 표준 함수 이기 때문에 COALESCE 함 수 를 사용 하 는 경향 이 있어 야 한다 고 생각 할 수도 있다.그렇다면 둘 이 어떻게 다른 지 함께 살 펴 보 자.
(1)COALESCE 와 ISNULL 처리 데이터 형식 우선 차이
COALESCE 함 수 는 형식 출력 을 데이터 형식 우선 순위[data type precedence]로 결정 하기 때문에 다음 과 같이 INT 를 처리 할 때 DATETIME 우선 순위 가 INT 보다 높 습 니 다.

DECLARE @int INT, @datetime DATETIME;
SELECT COALESCE(@datetime, 0);
SELECT COALESCE(@int, CURRENT_TIMESTAMP);

한편,ISNULL 함수 에 대해 데이터 형식 은 데이터 형식 에 우선 적 인 영향 을 받 지 않 고 함수 매개 변수 목록 의 첫 번 째 영향 을 받 습 니 다.ISNULL 은 교환 에 있 고 COALESCE 는 모든 매개 변수 조회 의 합병 에 있 습 니 다.

DECLARE @int INT, @datetime DATETIME;
SELECT ISNULL(@datetime, 0);

우 리 는 다음 과 같은 조작 을 진행 하 는 것 이 어떻게 되 는 지 보 자.

DECLARE @int INT, @datetime DATETIME;
SELECT ISNULL(@int, CURRENT_TIMESTAMP);
이때 DATETIME 을 INT 로 변환 할 수 없 는 상황 이 발생 합 니 다.

이때 우 리 는 명시 적 으로 다음 과 같은 전환 을 해 야 한다.

DECLARE @int INT, @datetime DATETIME;
SELECT ISNULL(@int, CONVERT(INT,CURRENT_TIMESTAMP));
SELECT ISNULL(@int, CAST(CURRENT_TIMESTAMP AS INT));
(2)ISNULL 은 데이터 손실 을 초래 합 니 다.
우 리 는 두 사람의 대비 예 를 다시 보 자.

DECLARE @c5 VARCHAR(5);
SELECT 'COALESCE', COALESCE(@c5, 'Jeffcky Wang')
UNION ALL
SELECT 'ISNULL', ISNULL(@c5, 'Jeffcky Wang');

위 에서 정의 한 문자열 변 수 는 길이 가 5 이 고 ISNULL 문자열 을 이용 하여 캡 처 되 었 습 니 다.여기 서 ISNULL 은 오류 가 아 닌 데 이 터 를 잃 어 버 릴 수 있다 고 생각 할 수 있 습 니 다.왜 이런 결과 가 나 왔 을 까?위 에서 말 했 듯 이 ISNULL 은 첫 번 째 매개 변수의 영향 을 받 아 길이 가 5 로 정의 되 기 때문에 5 로 만 정의 할 수 있 습 니 다.이것 은 캡 처 를 할 수 있 고 COALESCE 함 수 는 모든 요 소 를 검사 하 는 데 착안 하여 이 때 는 12 이기 때문에 완전히 되 돌아 갑 니 다.우 리 는 운행 을 통 해 아래 와 같이 볼 수 있다.

DECLARE @c5 VARCHAR(5);
SELECT 
 c = COALESCE(@c5, 'Jeffcky Wang'), 
 i = ISNULL(@c5, 'Jeffcky Wang')
INTO dbo.TestISNULL_COALESCE
SELECT name, t = TYPE_NAME(system_type_id), max_length, is_nullable
 FROM sys.columns
 WHERE [object_id] = OBJECT_ID('dbo.TestISNULL_COALESCE');
 
우 리 는 상술 한 COALESCE 합병 결과 가 비어 있 는 것 을 보 았 다.ISNULL 은 아니 라 조금 다르다.
(3)COALESCE 대 열 계산 시 지속 성 필요
다음은 두 사람의 가장 큰 차이 점 을 살 펴 보 겠 습 니 다.우 리 는 계산 열 을 통 해 그 위 에 메 인 키 나 비 어 있 는 제약 을 만 들 고 ISNULL 과 COALESCE 의 차 이 를 살 펴 보 겠 습 니 다.

CREATE TABLE dbo.CreateISNULL
(
 a INT,
 b AS ISNULL(a, 15) PRIMARY KEY
);

다시 한 번 COALESCE 함 수 를 보고 열 을 계산 해 보도 록 하 겠 습 니 다.

CREATE TABLE dbo.CreateCOALESCE
(
 a INT,
 b AS COALESCE(a, 15) PRIMARY KEY
);

열 을 지속 적 으로 유지 해 야 한 다 는 것 이 분명 합 니 다.PERSISTED 키 워드 를 추가 하면 다음 과 같 습 니 다.

CREATE TABLE dbo.CreateCOALESCE
(
 a INT,
 b AS COALESCE(a, 15) PERSISTED PRIMARY KEY
);
우리 둘 의 차 이 를 한 번 더 보 자.

DECLARE @c CHAR(10);
SELECT 'x' + COALESCE(@c, '') + 'y';
SELECT 'x' + ISNULL(@c, '') + 'y';

우 리 는 여기 서 사실 두 사람의 차 이 를 조금 요약 할 수 있다.ISNULL 은 교체 에 중심 을 두 고 COALESCE 는 합병 에 중심 을 둔다.COALESCE 는 NULL 을 무시 하고 빈 문자열 로 채 우 고 압축 하 는 것 을 보 여 줍 니 다.ISNULL 은 NULL 에 대해 빈 문자열 로 채 우지 만 압축 되 지 않 습 니 다.
(4)COALESCE 함 수 는 두 개 이상 의 인 자 를 지원 합 니 다.
여러 개의 매개 변수 입력 에 대해 ISNULL 함 수 는 내장 호출 이 필요 하 며,COALESCE 는 모든 수량 을 처리 할 수 있 으 며,상한 선 은 알 수 없 기 때문에 여러 매개 변수 에 대해 COALESCE 를 사용 하 는 것 은 다음 과 같 습 니 다.SELECT COALESCE(a, b, c, d, e, f, g) FROM dbo.table;ISNULL 에 대해 서 는 이렇게 해 야 합 니 다.SELECT ISNULL(a, ISNULL(b, ISNULL(c, ISNULL(d, ISNULL(e, ISNULL(f, g)))))) FROM dbo.table;양자 최종 집행 시 CASE 를 이용 하 는 것 과 같 습 니 다.

CASE   WHEN [tempdb].[dbo].[table].[a] IS NOT NULL THEN [tempdb].[dbo].[table].[a] 
 ELSE CASE WHEN [tempdb].[dbo].[table].[b] IS NOT NULL THEN [tempdb].[dbo].[table].[b] 
 ELSE CASE WHEN [tempdb].[dbo].[table].[c] IS NOT NULL THEN [tempdb].[dbo].[table].[c] 
 ELSE CASE WHEN [tempdb].[dbo].[table].[d] IS NOT NULL THEN [tempdb].[dbo].[table].[d] 
 ELSE CASE WHEN [tempdb].[dbo].[table].[e] IS NOT NULL THEN [tempdb].[dbo].[table].[e] 
 ELSE CASE WHEN [tempdb].[dbo].[table].[f] IS NOT NULL THEN [tempdb].[dbo].[table].[f] 
 ELSE [tempdb].[dbo].[table].[g] END END END END END END
(5)COALESCE 와 ISNULL 의 성능 비교
다음 조 회 를 실행 하 겠 습 니 다.

DBCC DROPCLEANBUFFERS;
DECLARE 
 @a VARCHAR(5), -- = 'str_a', -- this line changed per test
 @b VARCHAR(5), -- = 'str_b', -- this line changed per test
 @v VARCHAR(5), 
 @x INT   = 0,
 @time DATETIME2(7) = SYSDATETIME();
WHILE @x <= 500000
BEGIN
 SET @v = COALESCE(@a, @b); --COALESCE
 SET @x += 1;
END
SELECT DATEDIFF(MILLISECOND, @time, SYSDATETIME());
GO
DBCC DROPCLEANBUFFERS;
DECLARE 
 @a VARCHAR(5), -- = 'str_a', -- this line changed per test
 @b VARCHAR(5), -- = 'str_b', -- this line changed per test
 @v VARCHAR(5), 
 @x INT   = 0,
 @time DATETIME2(7) = SYSDATETIME();
WHILE @x <= 500000
BEGIN
 SET @v = ISNULL(@a, @b); --ISNULL
 SET @x += 1;
END
SELECT DATEDIFF(MILLISECOND, @time, SYSDATETIME());
우 리 는 네 개의 장면 을 조회 합 니 다.(1)두 개의 매개 변 수 는 모두 NULL(2)입 니 다.첫 번 째 매개 변 수 는 NULL(3)이 고 두 번 째 매개 변 수 는 NULL(4)입 니 다.두 개의 매개 변 수 는 모두 NULL 입 니 다.각 장면 에서 10 번 테스트 한 결과 다음 과 같은 결 과 를 얻 었 다.

위 에서 보 듯 이 이들 의 성능 은 큰 차이 가 없 기 때문에 우 리 는 너무 걱정 할 필요 가 없다.물론 상기 장면 은 완전히 덮 이지 않 았 고 적어도 일부분 은 설명 할 수 있다.상술 한 우리 가 얻 은 결과 조회 의 집행 시간 은 지금 다시 두 사람 이 집행 계획 을 조회 하 는 것 을 보 자.

SELECT COALESCE((SELECT MAX(index_id) FROM sys.indexes WHERE [object_id] = t.[object_id]), 0)
 FROM sys.tables AS t;
SELECT ISNULL((SELECT MAX(index_id) FROM sys.indexes WHERE [object_id] = t.[object_id]), 0)
 FROM sys.tables AS t;
 
상술 한 것 은 정확 하지 않 을 수도 있 고 하드웨어 설정 과 관련 이 있 을 수도 있 으 며,COALESCE 의 성능 이 ISNULL 과 떨 어 질 수도 있다.두 사람의 성능 은 큰 차이 가 없 을 것 이다.
(6)ISNULL 과 자연 언어 설명 이 일치 하지 않 음
왜 자연 언어 묘사 와 일치 하지 않 습 니까?즉,우 리 는 어떤 값 이 NULL 이 무엇 을 할 것 인지,NULL 을 위해 무엇 을 하지 않 을 것 인 지 를 판단 할 때 검색 언어 SQL 로 다음 과 같이 설명 합 니 다.

IF ISNULL(something)
 -- do something
우 리 는 자연 언어 로 볼 때 something 이 NULL 이 라면 우리 가 무엇 을 하 는 지,이 때 는 일치 하지 않 는 다.SQL Server 에 불 값 형식 이 없 기 때문에 다음 과 같은 변환 만 할 수 있 습 니 다.

IF something IS NULL
 -- do something
-- or
IF ISNULL(something, NULL) IS NULL
 -- do something
-- or
IF ISNULL(something, '') = ''
 -- do something
  (7)GUID 를 이용 해 진기한 ISNULL 을 본다.
이 절 이 소개 되 기 전에 우 리 는 다시 한 번 예 를 들 어 당신 의 생각 을 전복 시 켜 당신 을 미 치 게 합 니 다.SELECT ISNULL(NEWID(), 'JeffckyWang') AS Col1
이렇게 보면 문제 가 없다.우 리 는 그것 을 표 에 삽입 하고 그 열 에 대한 설명 을 본다.

SELECT ISNULL(NEWID(), 'JeffckyWang') AS Col1
INTO dbo.IsNullExample2;
EXEC sp_help 'dbo.IsNullExample2';

표 에 데이터 가 확실히 존재 하지만 열 에 대한 설명 은 비어 있 습 니 다.
총결산
상기 중점 은 COALESCE 와 ISNULL 함수 의 차이 점 을 다 루 었 습 니 다.이 절 을 통 해 두 사람의 장면 과 차 이 를 이야기 합 니 다.우 리 는 약간의 생각 을 가 져 야 합 니 다.도대체 COALESCE 를 사용 해 야 합 니까?ISNULL 을 사용 해 야 합 니까?대부분의 경우 COALESCE 를 이용 하 는 것 이 좋 습 니 다.하 나 는 이 함수 가 SQL 표준 함수 로 서 두 번 째 는 ISNULL 에 비해 더 많은 인 자 를 지원 할 수 있 고 ISNULL 은 내장 되 어야 합 니 다.ISNULL 에 대해 서 는 응용 장면 이 없 습 니까?물론 데 이 터 를 조회 할 때 데이터 가 NULL 인지 판단 하 는 경우 가 있 습 니 다.이런 상황 에서 ISNULL 을 이용 합 니 다.예 를 들 어 다음 과 같 습 니 다.

SELECT 
 ISNULL(argument, '') 
INTO dbo.IsNullExample;
본 고 는 ISNULL 과 COALESCE 에 관 한 비교 참고 글:Deciding between COALESCE and ISNULL in SQL Server.이 절 은 여기 서 마 치 겠 습 니 다.짧 은 내용,깊이 이해 하 겠 습 니 다.다음 절 에 뵙 겠 습 니 다.good night!
이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 댓 글 을 남 겨 서 교류 할 수 있 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다!

좋은 웹페이지 즐겨찾기