[sql-server] varchar와 nvarchar SQL Server 데이터 형식의 주요 성능 차이는 무엇입니까?

학교에서 소규모 웹 앱용 데이터베이스를 사용하고 SQL Server 2005있습니다.
나는 varchar대의 문제에 대한 두 개의 사고 학교를 봅니다.nvarchar .

  1. 사용하다 varchar 이 국제화 많은 양의 데이터를 처리하지 않으면, 다음 사용 nvarchar.
  2. 그냥 사용 nvarchar모든 것에 .

나는보기 2의 장점을보기 시작했다. 나는 nvarchar가 두 배의 공간을 차지한다는 것을 알고 있지만, 이것이 단지 수백 명의 학생들을 위해 데이터를 저장하기 때문에 큰 문제는 아닙니다. 나에게 그것은 걱정하지 않고 모든 것이 nvarchar를 사용하도록 허용하는 것이 가장 쉬운 것처럼 보입니다. 아니면 내가 놓친 것이 있습니까?



답변

항상 nvarchar를 사용하십시오.

대부분의 응용 프로그램에는 더블 바이트 문자가 필요하지 않을 수 있습니다. 그러나 2 바이트 언어를 지원해야하고 데이터베이스 스키마에서 1 바이트 만 지원하는 경우 애플리케이션 전체에서 돌아가서 수정하는 것이 실제로 비용이 많이 듭니다.

하나의 응용 프로그램을 varchar에서 nvarchar로 마이그레이션하는 데 드는 비용은 대부분의 응용 프로그램에서 사용할 약간의 추가 디스크 공간보다 훨씬 비쌉니다.


답변

디스크 공간은 문제가되지 않지만 메모리와 성능은 문제가됩니다. 페이지 읽기 두 배, 인덱스 크기 두 배, 이상한 LIKE 및 = 지속적인 동작 등

중국어 등 스크립트를 저장해야합니까? 예 혹은 아니오…

그리고 MS BOL에서 ” 유니 코드의 저장 및 성능 효과

편집 :

nvarchar 성능이 얼마나 나쁜지 강조하는 최근 SO 질문 …

SQL Server는 nvarchar 문자열 내부를 검색 할 때 높은 CPU를 사용합니다.


답변

일관성을 유지하십시오! VARCHAR에 NVARCHAR에 참여하면 성능이 크게 떨어집니다.


답변

NVARCHAR는 사양이 정말 것을 지시 그렇다면, 메모리, 스토리지, 작업 집합 및 인덱싱에 상당한 오버 헤드를해야 할 것입니다 결코 필요하지, 귀찮게하지 않습니다.

많은 상황에서, 특히 ASCII / EBCDIC의 ETL이나 키 및 외래 키인 식별자 및 코드 열에서 완전히 낭비 될 수 있기 때문에 어렵고 빠른 “항상 nvarchar”규칙을 갖지 않습니다.

반면에,이 질문에 일찍 물어볼 수있는 많은 열의 경우가 있으며, 단단하고 빠른 답변을 얻지 못하면 열을 nvarchar로 만듭니다.


답변

나는 이미 꽤 많은 것이 있기 때문에 여기에 또 다른 대답을 추가하는 것을 망설이지 않지만 명확하게 만들어지지 않았거나하지 않은 몇 가지 사항을 만들어야합니다.

첫째, 음주 하지 항상 사용합니다 NVARCHAR. 그것은 매우 위험하고 종종 비용이 많이 드는 태도 / 접근법입니다. ” 커서를 사용 하지 마십시오 “라고 말하는 것은 좋지 않습니다. 때로는 커서가 특정 문제를 해결하는 가장 효율적인 방법이기 때문에 WHILE루프 를 수행하는 일반적인 해결 방법 은 거의 항상 올바르게 수행되는 커서 보다 느립니다 .

“항상”이라는 용어를 사용해야하는 유일한 경우는 “항상 상황에 가장 적합한 것을 항상 수행”하는 것이 좋습니다. 특히 개발 시간의 단기적인 이익의 균형을 맞추려고 할 때 (관리자 : “지금까지 알지 못했던 일주일 전부터이 기능이 필요합니다!”) 균형을 잡을 때 결정하기가 어려운 경우가 많습니다. 장기 유지 보수 비용 (처음 3 주 스프린트에서 3 개월 프로젝트를 완료하도록 팀에 압력을 가한 관리자 : “이러한 성능 문제가 발생하는 이유는 무엇입니까? 유연성이없는 X를 어떻게 수행 할 수 있었습니까? 우리는 우선 순위 항목으로 돌아갈 수 있도록 일주일 동안 무엇을 할 수 있을까요? 그리고 디자인에서 더 많은 시간을 보내야만이 일이 계속 발생하지 않습니다! “).

둘째 : @gbn의 대답은 경로가 100 % 명확하지 않은 경우 특정 데이터 모델링 결정을 내릴 때 고려해야 할 매우 중요한 사항을 다룹니다. 그러나 고려해야 할 사항이 더 있습니다.

  • 트랜잭션 로그 파일의 크기
  • 복제하는 데 걸리는 시간 (복제를 사용하는 경우)
  • ETL에 걸리는 시간 (ETL의 경우)
  • 로그를 원격 시스템에 전달하고 복원하는 데 걸리는 시간 (로그 전달을 사용하는 경우)
  • 백업 크기
  • 백업을 완료하는 데 걸리는 시간
  • 복원하는 데 걸리는 시간 (언젠가 중요 할 수 있습니다 😉
  • tempdb에 필요한 크기
  • 트리거 성능 (tempdb에 저장된 삽입 및 삭제 된 테이블의 경우)
  • 행 버전 관리 성능 (버전 저장소가 tempdb에 있으므로 SNAPSHOT ISOLATION을 사용하는 경우)
  • CFO가 작년에 SAN에 백만 달러를 썼으며 추가 스토리지에 대해 2 억 5 천 달러를 더 이상 승인하지 않을 것이라고 CFO가 말하면 새로운 디스크 공간을 확보하는 능력
  • INSERT 및 UPDATE 작업을 수행하는 데 걸리는 시간
  • 인덱스 유지 관리를 수행하는 데 걸리는 시간

공간 낭비 는 전체 시스템에 영향을줍니다. 이 주제에 대한 명확한 세부 사항에 대한 기사를 작성했습니다 : Disk Is Cheap! 오랄? (무료 등록이 필요합니다. 해당 정책을 관리하지 않습니다.)

셋째 : 일부 답변은 ‘이것은 작은 앱입니다’측면에 잘못 초점을 맞추고 있으며 일부는 “적절한 것을 사용하는 것”을 올바르게 제안하고 있지만 답변 중 어느 것도 OP에 대한 실제 지침을 제공하지 않았습니다. 이 학교 웹 페이지입니다. 큰! 따라서 다음과 같이 제안 할 수 있습니다.

  • 학생 및 / 또는 교직원 이름에 대한 필드한다 아마 있을 NVARCHAR시간이 지남에, 그것은 단지 가능성이 다른 문화에서 이름이 그 장소에 표시됩니다지고, 이후.
  • 그러나 주소와 도시 이름은? 앱의 목적은 언급되지 않았지만 (도움이 되었음) 주소 레코드가있을 경우 특정 지리적 지역 (예 : 단일 언어 / 문화)과 관련된 것으로 가정 한 다음 VARCHAR적절한 코드 페이지 ( 필드의 데이터 정렬에서 결정됩니다).
  • 주 및 / 또는 국가의 ISO 코드 (저장소 필요없이 저장하면 INT/ TINYINTISO 코드가 고정되어 있기 때문에 길이, 사람이 읽을 수있는, 잘, 표준 : 사용 CHAR(2)두 글자 코드 및 CHAR(3)3 개 문자 코드를 사용하는 경우입니다. 그리고와 같은 이진 데이터 정렬 사용을 고려하십시오 Latin1_General_100_BIN2.
  • 우편 번호 (우편 번호)를 저장하는 경우 VARCHARAZ 이외의 문자를 사용하지 않는 것이 국제 표준이므로 사용하십시오. 그렇습니다. VARCHAR우편 번호는 숫자가 아니고 문자열이며 일부는 선행 “0”을 갖기 때문에 INT가 아닌 미국 우편 번호 만 저장하더라도 여전히 사용 합니다. 그리고와 같은 이진 데이터 정렬을 사용해보십시오 Latin1_General_100_BIN2.
  • 이메일 주소 및 / 또는 URL을 저장하는 경우 NVARCHAR둘 다 유니 코드 문자를 포함 할 수 있으므로 사용하십시오 .
  • 등등….

넷째 : 이제 NVARCHAR데이터가 잘 맞고 VARCHAR( “좋아요”= “?”로 바뀌지 않음) 데이터에 필요한 것보다 두 배 더 많은 공간을 차지하는 데이터를 가지게되었으므로 마치 마법에 의해 응용 프로그램이 커진 것처럼 이제 대부분의 행은 표준 ASCII이지만 일부는 유니 코드 문자를 포함하므로 이러한 필드 중 하나 이상에 수백만 개의 레코드가 있으므로 NVARCHAR다음을 고려하십시오.

  1. 당신은 SQL Server 2008을 사용하는 경우에는 – 2016 RTM을 하고 엔터프라이즈 에디션에있다, 또는 당신이 사용할 수 있습니다, 이상 (데이터 압축은 모든 버전에서 제공) SQL 서버 2016 SP1 사용하는 경우 데이터 압축을 . 데이터 압축은 필드 NCHARNVARCHAR필드 에서 유니 코드 데이터를 압축 할 수는 있지만 “항상”압축 할 수는 없습니다 . 결정 요인은 다음과 같습니다.

    1. NCHAR(1 - 4000)NVARCHAR(1 - 4000)사용 유니 코드 표준 압축 구성표 만 2008 R2, 및에서만 ROW 데이터를 SQL 서버에서 시작하지 OVERFLOW! 이것은 일반적인 ROW / PAGE 압축 알고리즘보다 나은 것으로 보입니다.
    2. NVARCHAR(MAX)그리고 XML(나는 또한 생각 VARBINARY(MAX), TEXT그리고 NTEXT) (하지 LOB 또는 용량 초과 페이지에서 행 OFF) 이상 PAGE 압축 할 수 있지만, IN ROW 데이터입니다 하지 압축 행. 물론 PAGE 압축은 행 내 값의 크기에 따라 다릅니다. VARCHAR (MAX)로 테스트 한 결과 6000 자 / 바이트 행이 압축되지 않지만 4000 자 / 바이트 행은 압축 된 것을 확인했습니다.
    3. 모든 ROW 데이터, LOB 또는 OVERLOW = 압축 없음!
  2. Enterprise Edition이 아닌 SQL Server 2005 또는 2008-2016 RTM을 사용하는 경우 하나 VARCHAR와 하나의 두 필드를 가질 수 있습니다 NVARCHAR. 예를 들어, 대부분 기본 ASCII 문자 (값 0-127) 인 URL을 저장한다고 가정 해 봅시다 VARCHAR. 그러나 때로는 유니 코드 문자를 갖습니다. 스키마에는 다음 3 개의 필드가 포함될 수 있습니다.

      ...
      URLa VARCHAR(2048) NULL,
      URLu NVARCHAR(2048) NULL,
      URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])),
      CONSTRAINT [CK_TableName_OneUrlMax] CHECK (
                        ([URLa] IS NOT NULL OR [URLu] IS NOT NULL)
                    AND ([URLa] IS NULL OR [URLu] IS NULL))
    );

    이 모델에서는 계산 열 에서만 SELECT합니다 [URL]. 삽입 및 업데이트의 경우 변환이 들어오는 값을 변경하는지 확인하여 사용할 필드를 결정합니다.이 값은 NVARCHAR유형 이어야 합니다.

    INSERT INTO TableName (..., URLa, URLu)
    VALUES (...,
            IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL),
            IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL)
           );
  3. 들어오는 값을 GZIP VARBINARY(MAX)한 다음 나갈 때 압축을 풀 수 있습니다 .

    • SQL Server 2005-2014의 경우 : SQLCLR을 사용할 수 있습니다. SQL # (내가 작성한 SQLCLR 라이브러리)은 무료 버전에서 Util_GZipUtil_GUnzip 과 함께 제공됩니다.
    • SQL 서버 2016 및 최신의 경우 : 당신이 사용할 수있는 내장 COMPRESSDECOMPRESS도 Gzip으로입니다 기능.
  4. SQL Server 2017 이상을 사용하는 경우 테이블을 Clustered Columnstore Index로 만들 수 있습니다.

  5. 아직 실행 가능한 옵션은 아니지만 SQL Server 2019에는 UTF-8 in VARCHAR/ CHARdatatypes 에 대한 기본 지원이 도입되었습니다 . 현재 사용할 버그가 너무 많지만 수정 된 경우 일부 시나리오에 대한 옵션입니다 . 이 새로운 기능에 대한 자세한 분석 은 내 게시물 ” SQL Server 2019의 기본 UTF-8 지원 : 구주 또는 거짓 예언자 “를 참조하십시오.


답변

응용 프로그램의 경우 데이터베이스 크기가 작기 때문에 nvarchar가 좋습니다. “항상 nvarchar 사용”이라고 말하는 것은 지나치게 단순화 된 것입니다. 간지 또는 다른 미친 캐릭터를 보관할 필요가없는 경우 VARCHAR을 사용하면 공간이 훨씬 적게 사용됩니다. 현재 직장의 전임자는 필요하지 않을 때 NVARCHAR을 사용하여 무언가를 설계했습니다. 우리는 최근에 그것을 VARCHAR로 바꾸고 그 테이블에 15GB를 절약했습니다. 또한 해당 테이블에 인덱스가 있고 해당 열을 포함하거나 복합 인덱스를 만들려는 경우 인덱스 파일 크기를 더 크게 만들었습니다.

당신의 결정에 신중하십시오. SQL 개발 및 데이터 정의에서 “기본 응답”은 거의없는 것 같습니다 (물론 커서를 피하는 것 이외).


답변

응용 프로그램이 작기 때문에 varchar보다 nvarchar를 사용하는 데 드는 비용이 크게 증가하지 않으며 유니 코드 데이터를 저장해야하는 경우 골치 아파할 수 있습니다.