테이블 정의의 열 순서가 중요합니까?


35

테이블을 정의 할 때는 목적에 따라 논리 그룹 및 그룹 자체의 열을 정렬하는 것이 좋습니다. 테이블에서 열의 논리적 순서는 개발자에게 의미를 전달하며 좋은 스타일의 요소입니다.

분명하다.

그러나 테이블에서 열의 논리적 순서가 스토리지 계층에서의 물리적 순서에 영향을 미치는지 또는 관심이있는 다른 영향이 있는지는 분명하지 않습니다.

스타일에 미치는 영향 외에도 열 순서가 중요합니까?

거기에있다 스택 오버플로에 대한 질문 이 약은 있지만, 권위있는 대답이 부족하다.

답변:


23

테이블에서 열의 논리적 순서가 스토리지 계층의 물리적 순서에 영향을 미칩니 까? 예.

중요한지 여부는 아직 대답 할 수없는 다른 문제입니다.

레코드 분석에 관한 Paul Randal의 자주 링크 된 기사에 설명 된 것과 유사한 방식으로 DBCC IND가 포함 된 간단한 두 개의 열 테이블을 살펴 보겠습니다.

SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;

USE master;
GO

IF DATABASEPROPERTY (N'RowStructure', 'Version') > 0 DROP DATABASE RowStructure;
GO

CREATE DATABASE RowStructure;
GO

USE RowStructure;
GO

CREATE TABLE FixedLengthOrder
(
    c1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , c2 CHAR(10) DEFAULT REPLICATE('A', 10) NOT NULL
    , c3 CHAR(10) DEFAULT REPLICATE('B', 10) NOT NULL  
);
GO

INSERT FixedLengthOrder DEFAULT VALUES;
GO

DBCC IND ('RowStructure', 'FixedLengthOrder', 1);
GO

DBCC IND 출력

위의 결과는 89 페이지를 봐야한다는 것을 보여줍니다.

DBCC TRACEON (3604);
GO
DBCC PAGE ('RowStructure', 1, 89, 3);
GO

DBCC PAGE의 출력에서 ​​c1은 c2의 'B'이전에 문자 'A'로 채워져 있습니다.

Memory Dump @0x000000000D25A060

0000000000000000:   10001c00 01000000 41414141 41414141 †........AAAAAAAA
0000000000000010:   41414242 42424242 42424242 030000††††AABBBBBBBBBB...

그리고 RowStructure.mdf16 진수 편집기로 버스트를 열고 'A'문자열이 'B'문자열보다 우선하는지 확인하십시오.

AAAAAAAAAA

이제 테스트를 반복하되 c1에 'B'문자를, c2에 'A'문자를 배치하여 문자열 순서를 반대로 바꿉니다.

CREATE TABLE FixedLengthOrder
(
    c1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , c2 CHAR(10) DEFAULT REPLICATE('B', 10) NOT NULL
    , c3 CHAR(10) DEFAULT REPLICATE('A', 10) NOT NULL  
);
GO

이번에는 DBCC PAGE 출력이 다르고 'B'문자열이 먼저 나타납니다.

Memory Dump @0x000000000FC2A060

0000000000000000:   10001c00 01000000 42424242 42424242 †........BBBBBBBB 
0000000000000010:   42424141 41414141 41414141 030000††††BBAAAAAAAAAA... 

다시, 낄낄 거림을 위해 데이터 파일의 16 진수 덤프를 확인하십시오.

BBBBBBBBBB

레코드 분석에서 설명 하는 것처럼 레코드 의 고정 길이 및 가변 길이 열은 별개의 블록에 저장됩니다. 논리적으로 인터리빙 고정 및 가변 열 유형은 물리적 레코드와 관련이 없습니다. 그러나 각 블록 내에서 열 순서는 데이터 파일의 바이트 순서로 매핑됩니다.

CREATE TABLE FixedAndVariableColumns
(
    c1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , c2 CHAR(10) DEFAULT REPLICATE('A', 10) NOT NULL
    , c3 VARCHAR(10) DEFAULT REPLICATE('B', 10) NOT NULL  
    , c4 CHAR(10) DEFAULT REPLICATE('C', 10) NOT NULL
    , c5 VARCHAR(10) DEFAULT REPLICATE('D', 10) NOT NULL
    , c6 CHAR(10) DEFAULT REPLICATE('E', 10) NOT NULL  
);
GO

Memory Dump @0x000000000E07C060

0000000000000000:   30002600 01000000 41414141 41414141 0.&.....AAAAAAAA 
0000000000000010:   41414343 43434343 43434343 45454545 AACCCCCCCCCCEEEE 
0000000000000020:   45454545 45450600 00020039 00430042 EEEEEE.....9.C.B 
0000000000000030:   42424242 42424242 42444444 44444444 BBBBBBBBBDDDDDDD 
0000000000000040:   444444†††††††††††††††††††††††††††††††DDD

참조 :

열 순서는 중요하지 않지만 일반적으로 – IT DEPENDS!


+1 동의합니다. 필자는 항상 각 섹션 내에서 열 순서가 CREATE TABLE명령문에 따른다는 것을 항상 발견했습니다 (CI 키 열이 섹션에서 먼저 오는 것을 제외하고). ALTER COLUMN데이터 유형 / 열 길이 가 변경되면 열 순서가 변경 될 수 있습니다 . 내가 생각할 수있는 유일한 사소한 경우는 빈 길이의 문자열 또는 NULL을 가진 가변 길이 섹션의 끝에있는 열이 열 오프셋 배열에서 공간을 전혀 차지하지 않는다는 것입니다 (2008 내부 책에서 Kalen Delaney에 의해 입증 됨)
마틴 스미스

1
드문 경우에는 열 순서가 중요 할 수 있습니다. 예를 들어, 열 A, B 및 C가 3 개인 테이블이있는 경우 각 길이는 3kb 바이트입니다. SQL Server 페이지는 8kb이므로 C적합하지 않으며 자체 확장 페이지로 이동합니다. 따라서 select A, BYourTable`에서 페이지 읽기의 절반 만 필요합니다 select A, C from YourTable.
Andomar

"Whether it matters or not is a different issue that I can't answer (yet).": 열의 순서는 성능에 큰 영향을 미칠 수 있으며 오류에도 영향을 줄 수 있습니다! 이것을 확인하십시오 -데모 2는 내가 생각하는 것이 더 좋습니다
Ronen Ariely

@RonenAriely 재미있는 예제이지만 원래 질문의 맥락에서 다소 고안되었습니다. 이후에 열을 삭제할 때 열 순서가 어떻게 영향을 미치는지 보여줍니다. 어떤 열을 떨어 뜨릴 지 예측할 수있는 테이블을 설계 한 적이 없다고 생각합니다.
Mark Storey-Smith

@ MarkStorey-Smith 님, 안녕하세요. (1) 건축가로서, 나는 우물 디자인과 위대한 디자인의 차이점은 좋은 디자인이 현재의 요구를 제공하는 반면 위대한 디자인은 아직 알려지지 않은 미래의 요구를 제공한다는 점을 항상 설명합니다. (2) 질문에 대한 대답은 순수합니다. 답변의 구현은 OP와 우리 각자에게 달려 있습니다. 이것은 논의의 범위를 벗어 났지만 토론을 위해이 주제를 열 수 있습니다. 하지만 유래 포럼의 가족, 인터페이스는 진정한 토론을 가지고 있지만 응답 텍스트의 한 가난한 짧은 줄을 추가하는 것을 허용하지 않기 때문에
Ronen에 애리 얼리

7

클러스터형 인덱스를 정의하지 않으면 힙 테이블이 생성됩니다. 힙 테이블의 경우 데이터를 읽을 때 항상 스캔하므로 전체 행을 읽고 열 순서를 약점으로 만듭니다.

클러스터형 인덱스를 정의하자마자 지정한대로 열의 물리적 순서에 맞게 데이터가 물리적으로 재정렬됩니다.이 시점에서 물리적 순서가 중요해집니다. 실제 순서는 사용중인 술어에 따라 탐색 연산자 자격을 결정합니다.

어디에서나 읽은 것을 기억할 수는 없지만 SQL Server는 힙의 실제 열 순서를 보장하지 않지만 인덱스는 보장한다고 가정합니다. 귀하의 질문에 대답하기 위해, 정의에서 열의 순서는 데이터를 읽을 때 중요하지 않기 때문에 중요하지 않습니다 (이것은 힙 에만 해당 -색인은 다른 문제입니다).

업데이트
실제로 두 가지 질문을합니다. "테이블의 열의 논리적 순서가 스토리지 계층에서의 물리적 순서에 영향을 미치는지 여부"는 아닙니다. 메타 데이터에 의해 정의 된 논리적 순서는 물리적 순서와 동일하지 않아도됩니다. 내가 모으고 싶은 것은 CREATE TABLE의 논리적 순서가 생성시 동일한 물리적 순서를 만드는지 여부입니다.


2

내가 본 내용을 기반으로 SQL Server의 열 순서는 차이가 없습니다. 스토리지 엔진은 CREATE TABLE 문에 지정된 방식에 관계없이 행에 열을 배치합니다. 즉, 문제가되는 매우 고립 된 엣지 사례가 있다고 확신하지만 이것에 대해 단 하나의 결정적인 대답을 얻는 데 어려움을 겪을 것이라고 생각합니다. Paul Randal의 " 스토리지 엔진 내부"블로그 카테고리 게시물은 내가 알고있는 스토리지 엔진의 작동 방식에 대한 모든 세부 정보를 제공하는 최고의 소스입니다. 스토리지 사용 방식과 모든 사용 사례에 대한 매트릭스를 다양하게 연구해야한다고 생각합니다. 내 상황에 적용되는 특정 사례가 지적되지 않는 한 CREATE TABLE에서 열을 논리적으로 주문하면 도움이되기를 바랍니다.


1

무슨 말인지 알 겠어 디자인 관점에서 다음과 같은 테이블이 표시됩니다.

**EMPLOYEES**
EmployeeID
FirstName
LastName
Birthday
SSN 

다음과 같은 테이블보다 훨씬 낫습니다.

**EMPLOYEES**
LastName
EmployeeID
SSN 
Birthday
FirstName

그러나 데이터베이스 엔진은 다음과 같이 tsql을 발행하면 논리적 열 순서를 실제로 신경 쓰지 않습니다.

SELECT FirstName, LastName, SSN FROM Employees

엔진은 FirstName 목록이 디스크에서 저장되는 위치 만 알고 있습니다.

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