SQL Server 2005에서 nvarchar (255)와 같이 길이를 명시 적으로 지정하지 않고 모든 문자 필드를 nvarchar (MAX)로 만드는 데 단점이 있습니까? (데이터베이스 수준에서 필드 길이를 제한 할 수 없다는 것은 분명합니다)
SQL Server 2005에서 nvarchar (255)와 같이 길이를 명시 적으로 지정하지 않고 모든 문자 필드를 nvarchar (MAX)로 만드는 데 단점이 있습니까? (데이터베이스 수준에서 필드 길이를 제한 할 수 없다는 것은 분명합니다)
답변:
MSDN 포럼에서도 동일한 질문이 제기되었습니다.
원래 게시물에서 (더 많은 정보가 있습니다) :
VARCHAR (N) 열에 데이터를 저장할 때 값은 실제로 동일한 방식으로 저장됩니다. 그러나 VARCHAR (MAX) 열에 저장하면 화면 뒤에서 데이터가 TEXT 값으로 처리됩니다. 따라서 VARCHAR (MAX) 값을 처리 할 때 몇 가지 추가 처리가 필요합니다. (크기가 8000을 초과하는 경우에만)
VARCHAR (MAX) 또는 NVARCHAR (MAX)는 '큰 값 유형'으로 간주됩니다. 큰 값 유형은 일반적으로 'out of row'로 저장됩니다. 데이터 행에 '큰 값'이 저장된 다른 위치에 대한 포인터가 있음을 의미합니다 ...
N/VARCHAR(MAX)
"크기가 8000을 초과하는 경우에만"추가 처리가 있기 때문에 대답을 "아니오, 사용에 불리한 점이 없습니다"로 읽었습니다 . 따라서 필요한 경우에만 비용이 발생하며 데이터베이스의 제약 이 적습니다 . 이것을 잘못 읽고 있습니까? 당신은 거의 항상 N/VARCHAR(MAX)
보다는 오히려 원하는 것 같습니다 N/VARCHAR(1-8000)
...
sp_tableoptions
: msdn.microsoft.com/en-us/library/ms173530.aspx . VARCHAR (255) 유형은 또한 행 밖으로 밀릴 수 있습니다. 언급 된 '오버 헤드'는 MAX와 255에 대해 정확히 동일 할 수 있습니다. MAX 유형과 텍스트 유형이 구별 될 때 TEXT 유형과 비교합니다 (완전히 다른 API 조작, 다른 저장 등). 실제 차이점을 언급하지 못했습니다 : 색인 없음, MAX 유형에 대한 온라인 작업 없음
그것은 공정한 질문이며 명백한 것과는 별개로 진술했습니다…
단점은 다음과 같습니다.
성능 영향 쿼리 최적화 프로그램은 필드 크기를 사용하여 가장 효율적인 실행 계획을 결정합니다.
"1. 데이터베이스의 확장 영역과 페이지의 공간 할당이 유연합니다. 따라서 업데이트를 사용하여 필드에 정보를 추가 할 때 새 데이터가 이전에 삽입 된 것보다 길면 데이터베이스가 포인터를 작성해야합니다.이 데이터베이스 파일은 인덱스에서 삭제, 업데이트 및 삽입에 이르기까지 거의 모든 부분에서 성능이 저하됨 = " http://sqlblogcasts.com/blogs/simons/archive/2006/02/28/Why-use-anything-but-varchar_2800_max_2900_.aspx
통합 시사점-다른 시스템이 데이터베이스와 통합하는 방법을 알기 어렵다 예상치 못한 데이터 증가 가능한 보안 문제 (예 : 모든 디스크 공간을 차지하여 시스템 충돌)
여기에 좋은 기사가 있습니다 : http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1098157,00.html
varchar(max)
.
허용 된 답변에 제공된 링크를 기반으로 다음과 같이 나타납니다.
nvarchar(MAX)
필드에 저장된 100 문자는 필드에 100 문자와 다르지 않게 저장됩니다 nvarchar(100)
. 데이터는 인라인으로 저장되며 데이터를 'out of row'로 읽고 쓰는 오버 헤드가 없습니다. 그래서 걱정할 필요가 없습니다.
크기가 4000보다 크면 데이터가 자동으로 'out of row'로 저장됩니다. 그래서 걱정도 없습니다.
하나...
nvarchar(MAX)
열에 . 전체 텍스트 인덱싱을 사용할 수 있지만 쿼리 성능을 향상시키기 위해 열에 인덱스를 만들 수는 없습니다. 나에게 이것은 거래를 봉쇄합니다 ... 항상 nvarchar (MAX)를 사용하는 것이 확실한 단점입니다.결론:
인덱싱 할 수 있고 공간과 액세스 시간을 낭비하지 않는 전체 데이터베이스에서 일종의 "유니버설 문자열 길이"를 원한다면을 사용할 수 있습니다 nvarchar(4000)
.
nvarchar(max)
처럼 - 모든 시간을 string
C #으로? -그러나 포인트 3) (색인 문제)이 답을주고 있습니다.
nvarchar(4000)
때로는 데이터 유형이 데이터에 의미를 부여하기를 원할 때가 있습니다.
예를 들어 실제로 20 자보다 길면 안되는 열이 있다고 가정하십시오. 해당 열을 VARCHAR (MAX)로 정의하면 일부 불량 응용 프로그램에서 긴 문자열을 삽입 할 수 있으며 알 수 없거나 방지 할 방법이 없습니다.
다음에 응용 프로그램에서 해당 문자열을 사용할 때 문자열의 길이가 적당하고 문자열이 대표하는 도메인이라는 가정하에 예측할 수없고 혼란스러운 결과가 발생합니다.
내가 어떤 기사를 확인하고이에서 유용한 테스트 스크립트를 찾을 수 : http://www.sqlservercentral.com/Forums/Topic1480639-1292-1.aspx은 다음 NVARCHAR 대 NVARCHAR (4000) 대 NVARCHAR (10) (MAX 사이의 비교를 변경 )와 지정된 숫자를 사용할 때 속도 차이를 찾지 못하지만 MAX를 사용할 때. 혼자서 테스트 할 수 있습니다. 희망이 도움이됩니다.
SET NOCOUNT ON;
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(10)
DECLARE @SomeString NVARCHAR(10),
@StartTime DATETIME;
--=====
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='10', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(4000)
DECLARE @SomeString NVARCHAR(4000),
@StartTime DATETIME;
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='4000', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(MAX)
DECLARE @SomeString NVARCHAR(MAX),
@StartTime DATETIME;
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='MAX', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
max 또는 text 필드를 사용하지 않는 이유는 SQL Server Enterprise Edition에서도 온라인 인덱스 재 구축을 수행 할 수 없기 때문입니다. 즉 REBUILD WITH ONLINE = ON입니다.
필드가 예를 들어 5 ~ 10 자 범위로 설정 될 경우 잘못된 생각입니다. 길이가 무엇인지 확실하지 않은 경우 max 만 사용한다고 생각합니다. 예를 들어 전화 번호는 특정 문자 수를 넘지 않아야합니다.
테이블의 모든 필드에 대한 대략적인 길이 요구 사항이 확실하지 않다고 정직하게 말할 수 있습니까?
나는 당신의 요점을 얻습니다-varchar (max) 사용을 확실히 고려할만한 필드가 있습니다.
흥미롭게도 MSDN 문서는 다음과 같이 요약합니다.
열 데이터 항목의 크기가 상당히 다른 경우 varchar을 사용하십시오. 열 데이터 항목의 크기가 상당히 다양하고 크기가 8,000 바이트를 초과 할 경우 varchar (max)를 사용하십시오.
데이터베이스의 역할은 엔터프라이즈에서 사용할 수 있도록 데이터를 저장하는 것입니다. 그 데이터를 유용하게 만드는 것의 일부는 그것이 의미가 있는지 확인하는 것입니다. 누군가 이름을 무제한으로 입력 할 수 있다고해서 의미있는 데이터가 보장되는 것은 아닙니다.
이러한 제약 조건을 비즈니스 계층에 구축하는 것이 좋지만 데이터베이스가 그대로 유지되는 것은 아닙니다. 데이터 규칙을 위반하지 않도록하는 유일한 방법은 데이터베이스에서 가능한 가장 낮은 수준에서 규칙을 시행하는 것입니다.
한 가지 문제는 여러 버전의 SQL Server로 작업해야하는 경우 MAX가 항상 작동하지는 않는다는 것입니다. 따라서 레거시 DB 또는 여러 버전과 관련된 다른 상황에서 작업하는 경우 매우 조심해야합니다.
위에서 지적한 바와 같이, 이는 주로 스토리지와 성능 사이의 균형점입니다. 적어도 대부분의 경우.
그러나 n / varchar (n) 대신 n / varchar (Max)를 선택할 때 고려해야 할 다른 요소가 하나 이상 있습니다. 데이터의 색인이 생성됩니까 (예 : 성)? MAX 정의는 LOB로 간주되므로 MAX로 정의 된 것은 색인 작성에 사용할 수 없습니다. 인덱스가 없으면 WHERE 절에서 술어로서 데이터를 포함하는 모든 조회는 전체 테이블 스캔으로 강제 실행되며 이는 데이터 조회에서 얻을 수있는 최악의 성능입니다.
1) nvarchar (max) vs nvarchar (n)을 처리 할 때 SQL 서버는 더 많은 리소스 (할당 된 메모리 및 CPU 시간)를 사용해야합니다. 여기서 n은 필드 고유의 숫자입니다.
2) 이것은 성능과 관련하여 무엇을 의미합니까?
SQL Server 2005에서는 15 개의 nvarchar (max) 열이있는 테이블에서 13,000 행의 데이터를 쿼리했습니다. 쿼리 시간을 반복 한 다음 열을 nvarchar (255) 이하로 변경했습니다.
최적화 이전의 쿼리는 평균 2.0858 초입니다. 변경 후 쿼리는 평균 1.90 초 내에 반환됩니다. 기본 select * 쿼리가 약 184 밀리 초 개선되었습니다. 8.8 % 개선 된 것입니다.
3) 내 결과는 성능 차이가 있음을 나타내는 다른 기사와 일치합니다. 데이터베이스와 쿼리에 따라 개선 비율이 달라질 수 있습니다. 동시 사용자가 많지 않거나 레코드가 많지 않으면 성능 차이가 문제가되지 않습니다. 그러나 더 많은 레코드와 동시 사용자가 증가함에 따라 성능 차이가 증가합니다.
내 테스트에서 선택할 때 차이점이 있음을 보여주었습니다.
CREATE TABLE t4000 (a NVARCHAR(4000) NULL);
CREATE TABLE tmax (a NVARCHAR(MAX) NULL);
DECLARE @abc4 NVARCHAR(4000) = N'ABC';
INSERT INTO t4000
SELECT TOP 1000000 @abc4
FROM
master.sys.all_columns ac1,
master.sys.all_columns ac2;
DECLARE @abc NVARCHAR(MAX) = N'ABC';
INSERT INTO tmax
SELECT TOP 1000000 @abc
FROM
master.sys.all_columns ac1,
master.sys.all_columns ac2;
SET STATISTICS TIME ON;
SET STATISTICS IO ON;
SELECT * FROM dbo.t4000;
SELECT * FROM dbo.tmax;
흥미로운 링크 : TEXT를 사용할 수 있는데 왜 VARCHAR을 사용합니까?
PostgreSQL과 MySQL에 관한 것이기 때문에 성능 분석은 다르지만 "명시 성"에 대한 논리는 여전히 남아 있습니다. 이메일 주소를 변수에 저장 한 경우 '문자열은 80 자로 제한되지 않은 문자열'이 아닌 '문자열'을 사용합니다.
내가 볼 수있는 주요 단점은 당신이 이것을 가지고 있다고 가정 해 봅시다.
UI에 필요한 데이터에 대한 정보를 가장 많이 제공하는 것은 무엇입니까?
이
CREATE TABLE [dbo].[BusData](
[ID] [int] IDENTITY(1,1) NOT NULL,
[RecordId] [nvarchar](MAX) NULL,
[CompanyName] [nvarchar](MAX) NOT NULL,
[FirstName] [nvarchar](MAX) NOT NULL,
[LastName] [nvarchar](MAX) NOT NULL,
[ADDRESS] [nvarchar](MAX) NOT NULL,
[CITY] [nvarchar](MAX) NOT NULL,
[County] [nvarchar](MAX) NOT NULL,
[STATE] [nvarchar](MAX) NOT NULL,
[ZIP] [nvarchar](MAX) NOT NULL,
[PHONE] [nvarchar](MAX) NOT NULL,
[COUNTRY] [nvarchar](MAX) NOT NULL,
[NPA] [nvarchar](MAX) NULL,
[NXX] [nvarchar](MAX) NULL,
[XXXX] [nvarchar](MAX) NULL,
[CurrentRecord] [nvarchar](MAX) NULL,
[TotalCount] [nvarchar](MAX) NULL,
[Status] [int] NOT NULL,
[ChangeDate] [datetime] NOT NULL
) ON [PRIMARY]
아니면 이거?
CREATE TABLE [dbo].[BusData](
[ID] [int] IDENTITY(1,1) NOT NULL,
[RecordId] [nvarchar](50) NULL,
[CompanyName] [nvarchar](50) NOT NULL,
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[ADDRESS] [nvarchar](50) NOT NULL,
[CITY] [nvarchar](50) NOT NULL,
[County] [nvarchar](50) NOT NULL,
[STATE] [nvarchar](2) NOT NULL,
[ZIP] [nvarchar](16) NOT NULL,
[PHONE] [nvarchar](18) NOT NULL,
[COUNTRY] [nvarchar](50) NOT NULL,
[NPA] [nvarchar](3) NULL,
[NXX] [nvarchar](3) NULL,
[XXXX] [nvarchar](4) NULL,
[CurrentRecord] [nvarchar](50) NULL,
[TotalCount] [nvarchar](50) NULL,
[Status] [int] NOT NULL,
[ChangeDate] [datetime] NOT NULL
) ON [PRIMARY]
한 가지 단점은 예측할 수없는 변수를 중심으로 설계한다는 점이며, 행, 페이지 및 범위로 점진적으로 구성된 내부 SQL Server 데이터 구조를 이용하는 대신 무시할 수 있습니다.
데이터 구조 정렬 에 대해 생각하게 만듭니다.C에서 에 을 인식하는 것은 일반적으로 Good Thing (TM)으로 간주됩니다. 비슷한 생각, 다른 맥락.
페이지 및 범위에 대한 MSDN 페이지
행 오버플로 데이터에 대한 MSDN 페이지
먼저 나는 이것에 대해 생각했지만 다시 생각했다. 성능에 영향을 미치지 만 필드의 실제 크기를 알기위한 문서 형식으로 사용됩니다. 또한 데이터베이스가 더 큰 생태계에있을 때 시행합니다. 제 생각에는 열쇠는 허용 적이지만 이성적인 것이어야합니다.
자, 여기 비즈니스 및 데이터 계층 논리 문제에 대한 느낌이 있습니다. DB가 비즈니스 로직을 공유하는 시스템간에 공유 리소스 인 경우 당연히 그러한 로직을 적용하는 것이 자연스럽게 보이지만 최선의 방법은 아니지만 API를 제공하는 것이 가장 좋습니다. 테스트 할 상호 작용은 비즈니스 로직이 속해있는 곳에서 유지하고, 시스템을 분리 된 상태로 유지하고, 시스템 내 계층을 분리 된 상태로 유지합니다. 그러나 데이터베이스가 하나의 응용 프로그램 만 제공해야한다면 AGILE을 생각해 보도록하겠습니다. 지금은 디자인. 그러한 액세스가 필요한 경우 해당 데이터에 대한 API를 제공하십시오.
그러나 기존 시스템으로 작업하는 경우 적어도 단기적으로는 다르게 수행해야 할 가능성이 높습니다.
데이터베이스가 작은 경우 실제 문제가 발생하지 않을 수 있지만 성능 문제가 발생합니다. 각 레코드는 하드 드라이브에서 더 많은 공간을 차지하며 한 번에 많은 레코드를 검색하는 경우 데이터베이스는 더 많은 디스크 섹터를 읽어야합니다. 예를 들어, 작은 레코드는 섹터에 50을, 큰 레코드는 5에 맞을 수 있습니다. 큰 레코드를 사용하여 디스크에서 10 배 많은 데이터를 읽어야합니다.
nvarchar(max)
열에 저장된 길이 100의 문자열은 열에있는 것보다 더 많은 디스크 공간을 차지하지 않습니다 nvarchar(100)
.