`nvarchar / nchar`가 SQL Server 2019와 함께 사용될 예정입니까?


11

SQL 서버 2019 마이크로 소프트 소개와 UTF-8 지원 에 대한 CHARVARCHAR데이터 유형을 다음과 같이 말한다 :

이 기능은 사용중인 문자 세트에 따라 스토리지를 크게 절약 할 수 있습니다. 예를 들어, UTF-8 사용 데이터 정렬을 사용하여 ASCII 문자열이있는 기존 열 데이터 유형을 NCHAR (10)에서 CHAR (10)으로 변경하면 스토리지 요구 사항이 거의 50 % 감소합니다. 이 감소는 NCHAR (10)에 22 바이트의 저장 공간이 필요하고 CHAR (10)에는 동일한 유니 코드 문자열에 12 바이트가 필요하기 때문입니다.

UTF-8은 것 같다 지원 하므로 기본적으로 우리가 유니 코드 데이터를 저장하기 시작, 모든 스크립트 varcharchar열. 그리고 문서에서 말했듯이, 이것은 테이블과 인덱스의 크기를 줄일 수 있으며 더 적은 양의 데이터를 읽으므로 더 나은 성능을 얻을 수 있습니다.

나는 이것이 우리가 사용 중지 할 수 있습니다 의미합니까 궁금 nvarchar하고 nchar열이있는 구현 UTF-16?

누구나 char 데이터 유형을 UTF인코딩과 함께 사용하지 않고 n 문자 유형을 계속 사용 하지 않도록 시나리오와 이유를 지적 할 수 있습니까 ?


왜 테스트하고 다시보고하지 않습니까? 또한 nvarchar에서 varchar로 변환하는 데 얼마나 많은 노력을 기울 였는지, alter table에 걸린 시간, 테스트에 소요 된 시간, 발생한 문제 등을 알려주십시오.
Colin 't Hart

@ Colin'tHart 알려진 문제 나 고려 사항이없는 경우 적은 양의 데이터를 읽으면 시스템 성능이 향상 될 것으로 예상되므로 데이터를 마이그레이션 할 계획입니다. 변환에 대해-물론 주어진 열이있는 인덱스가있는 경우 시간이 걸릴 것입니다-다시 작성해야하지만 잘 지불 할 것이라고 믿습니다. 물론 마이그레이션이 불필요하게 만드는 문제를 찾아서 성능에 미치는 영향을 곧 테스트 할 것입니다.
gotqn

SQL Server는 PAGE 또는 ROW 압축을 사용할 때 NVarchar 열에 대한 유니 코드 압축을 지원합니다.
David Browne-Microsoft

1
UTF-8은 "ASCII와 유사한 데이터"를 저장하는 경우 공간을 절약 할 수 있지만 압축 자체가 아니기 때문에 실수로 잘못해서는 안됩니다. 예를 들어, 주로 중국어 이름을 데이터베이스에 저장하는 CHAR경우 유니 코드 유형보다 UTF-8 유형을 사용하는 것이 더 나빠질 수 있습니다 (압축 유무에 관계없이 처리를 위해서는 데이터를 압축 해제해야하므로). Windows의 기본 문자열 유형은 유니 코드이므로 UTF-8 문자열은 종종 디코딩해야합니다. 관련된 트레이드 오프는 해당 N유형이 곧 폐기 될 가능성이 낮음을 의미합니다 .
Jeroen Mostert

1
CHAR엔진이 문자열을 UTF-8로 직접 처리하는 기본 지원을 얻는 경우 UTF-8의 # 1 "킬러 앱"은 Linux의 SQL Server 일 것입니다. 여기서 UTF-8은 "네이티브"문자 집합입니다. UTF-16으로 문자열을 유지하는 것이 덜 효율적인 대안입니다. CHAR저장할 수있는 문자를 제한하는 데이터 정렬이 매력적이지 않았기 때문에 이미 이미 사용중인 위치에서 Windows에서 사용하는 것은 아프지 않습니다 .
Jeroen Mostert

답변:


6

이것은 테이블과 인덱스의 크기를 줄일 있습니다 (강조 추가)

경우 크기가 감소에만 가능 대부분의 문자는 본질적으로 [space], 0 - 9, A - Z, a - z, 그리고 몇 가지 기본적인 문장 부호. (실제 사용 조건, 표준 ASCII 값 32 - 126) 문자의 특정 세트의 외부, 당신은 할 것이다 가장에서 크기가 같아 NVARCHAR/ UTF-16, 또는 많은 경우 더 큰있다.

적은 양의 데이터를 읽으면 시스템 성능이 향상 될 것으로 예상되므로 데이터를 마이그레이션 할 계획입니다.

조심해. UTF-8은 마술 "모든 것을 고치십시오"스위치가 아닙니다. 다른 모든 것들이 동일합니다. 예, 읽기가 적을수록 성능이 향상됩니다. 그러나 여기서 "다른 모든 것"은 같지 않습니다 . 표준 ASCII 문자 저장하는 경우 에도 (모든 문자가 1 바이트이므로에 저장하는 것과 비교하여 절반의 공간이 필요함 NVARCHAR) UTF-8을 사용하면 약간의 성능 저하가 있습니다. 나는 UTF-8이 가변 길이 인코딩이기 때문에 문제가 있다고 생각합니다. 즉, 각 바이트가 완전한 문자인지 또는 다음 바이트가 그 일부인지를 알기 위해서는 읽은대로 해석해야합니다. 이것은 모든 문자열 연산이 시작에서 시작하여 바이트 단위로 진행되어야 함을 의미합니다. 반면에NVARCHAR / UTF-16은 항상 2 바이트 (보충 문자는 2 바이트 코드 포인트 2 개로 구성됨)이므로 2 바이트 청크로 읽을 수 있습니다.

필자의 테스트에서는 표준 ASCII 문자 만 사용 하더라도 데이터를 UTF-8로 저장하면 경과 시간을 절약 할 수 없었지만 CPU 시간은 확실히 나빴습니다. 그리고 그것은 데이터 압축이 없었기 때문에 최소한 사용 된 디스크 공간이 적었습니다. 그러나 압축을 사용할 때 UTF-8에 필요한 공간은 1 %-1.5 % 작았습니다. 따라서 UTF-8의 경우 공간을 절약하면서도 CPU 시간을 효과적으로 늘릴 수 있습니다.

NVARCHAR(MAX)값이 행에 저장하기에 충분히 작더라도 유니 코드 압축은 해당 데이터 유형에서 작동하지 않으므로 사용시 상황이 더 복잡해집니다 . 그러나 데이터가 충분히 작 으면 여전히 행 또는 페이지 압축의 이점을 누릴 수 있습니다 (이 경우 실제로 UTF-8보다 빠릅니다). 그러나 행 외부 데이터는 압축을 사용할 수 없습니다. 그럼에도 불구하고 테이블을 Clustered Columnstore Index로 만들면 크기가 크게 줄어 듭니다 NVARCHAR(MAX)(Clustered Columnstore Index를 사용할 때 UTF-8보다 약간 더 큰 경우에도).

UTF 인코딩과 함께 char 데이터 유형을 사용하지 말고 시나리오와 이유를 지적 할 수 있습니까?

명확히. 사실, 나는 대부분의 경우에 그것을 사용해야 할 강력한 이유를 찾지 못한다. UTF-8의 진정한 이점은 다음과 같습니다.

  1. 데이터는 대부분 표준 ASCII입니다 (값 0-127)
  2. 그것은 때문에 유니 코드를 할 필요가 있습니다 단일 8 비트에 코드 페이지 (즉, 사용할 수있는 것보다 문자의 넓은 범위를 저장해야합니다 VARCHAR)
  3. 대부분의 데이터는 행 외부에 저장되므로 페이지 압축은 작동하지 않습니다.
  4. 쿼리 성능이 아닌 이유로 크기를 줄이고 자하는 데이터가 충분합니다 (예 : 백업 크기 감소, 백업 / 복원에 필요한 시간 감소 등).
  5. Clustered Columnstore Index를 사용할 수 없습니다 (이 경우 테이블을 사용하면 성능이 저하됩니까?)

내 테스트에 따르면 거의 모든 경우에 특히 NVARCHAR이 더 빠르며 특히 데이터가 많을수록 더 빠릅니다. 실제로 행당 평균 5k 문자 의 21k 행에는 UTF-8의 경우 165MB, NVARCHAR압축되지 않은 경우 236MB가 필요합니다. 그러나 NVARCHAR경과 시간은 2 배 빨라졌으며 CPU 시간은 2 배 이상 빨랐습니다. 여전히 디스크에서 71MB 이상을 차지했습니다.

그 외에도이 기능에서 발견 된 다양한 버그로 인해 적어도 CTP 2에서 UTF-8을 사용하지 않는 것이 좋습니다.

UTF-16과 UTF-8의 차이점에 대한 설명 및 해당 버그 목록을 포함하여이 새로운 기능에 대한 자세한 분석은 내 게시물을 참조하십시오.

SQL Server 2019의 기본 UTF-8 지원 : 구주 또는 거짓 예언자?


12

UTF-8 지원은 새로운 옵션 세트를 제공합니다. 잠재적 인 공간 절약 ( 행 또는 페이지 압축 제외)은 한 가지 고려 사항이지만 유형 및 인코딩 선택은 주로 비교, 정렬, 데이터 가져 오기 및 내보내기에 대한 실제 요구 사항을 기반으로해야합니다 .

예를 들어 nchar(1)유형은 2 바이트의 저장 공간을 제공 하므로 생각보다 많이 변경해야 할 수도 있습니다 . BMP에 코드 를 저장하기에 충분합니다 (코드 포인트 000000 ~ 00FFFF). 해당 범위의 일부 문자는 UTF-8에서 1 바이트로 인코딩되는 반면 다른 문자는 2 바이트 또는 3 바이트가 필요합니다 (자세한 내용은 이 비교 차트 참조). 따라서 UTF-8에서 동일한 문자 세트의 적용 범위를 보장하려면이 필요합니다 char(3).

예를 들면 다음과 같습니다.

DECLARE @T AS table 
(
    n integer PRIMARY KEY,
    UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
    UTF8 char(1) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);

INSERT @T (n, UTF16, UTF8)
SELECT 911, NCHAR(911), NCHAR(911);

익숙한 오류를 제공합니다.

메시지 8152, 수준 16, 상태 30, 줄 xxx
문자열 또는 이진 데이터가 잘립니다.

또는 추적 플래그 460이 활성화 된 경우 :

메시지 2628, 수준 16, 상태 1, 줄 xxx
문자열 또는 이진 데이터는 테이블 '@T', 열 'UTF8'에서 잘립니다. 잘린 값 : ''.

에 UTF8 열을 확장 char(2)하거나 varchar(2)에 대한 오류를 해결합니다 NCHAR(911):

DECLARE @T AS table 
(
    n integer PRIMARY KEY,
    UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
    UTF8 varchar(2) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);

INSERT @T (n, UTF16, UTF8)
SELECT 911, NCHAR(911), NCHAR(911);

그러나 예를 들어 NCHAR(8364)이면 열을 추가로 char(3)또는 로 확장해야합니다 varchar(3).

UTF-8 데이터 정렬은 모두 보충 문자를 사용하므로 복제 작업수행 할 수 없습니다 .

UTF-8 지원은 현재 다른 것 외에는 미리보기에서만 제공되므로 프로덕션 용도로는 사용할 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.