각 열에 대해 사전 정의 된 데이터 유형을 설정하여 관계형 데이터베이스는 무엇을 얻습니까?


44

나는 지금 SQL 데이터베이스를 사용하고 있는데, 이것이 항상 호기심을 불러 일으켰지 만 Google 검색은 많이 나오지 않습니다. 왜 엄격한 데이터 유형입니까?

이진 데이터와 일반 텍스트 데이터를 구별하는 방법과 같이 몇 가지 다른 데이터 유형을 갖는 이유를 이해 합니다 . 1과 0의 이진 데이터를 일반 텍스트로 저장하는 대신 이진 데이터를 자체 형식으로 저장하는 것이 더 효율적이라는 것을 이해합니다.

그러나 내가 이해 하지 못하는 것은 많은 다른 데이터 유형 을 갖는 이점이 있다는 것입니다 .

  • mediumtext, longtext그리고 text?
  • decimal, float그리고 int?
  • 기타

데이터베이스에 "이 열의 항목에는 256 바이트의 일반 텍스트 데이터 만있을 것"이라는 이점이 있습니다. 또는 "이 열에는 최대 16,777,215 바이트의 텍스트 항목이있을 수 있습니다"?

성능상의 이점입니까? 그렇다면 왜 사전에 출품작의 크기를 아는 것이 성과에 도움이됩니까? 아니면 오히려 다른 무엇입니까?


2
나는이 질문이 이미 존재해야한다고 생각했지만 사이트를 검색했지만 유용한 것을 찾지 못했습니다.
john doe


6
당신이 구별되어 있지 않은 경우 decimal, floatint유형, 당신은 무엇을 기대 1 / 3할까? 무엇에 대해 1.0 / 3.0? 당신은 당신이 나눌 때 확신 할 수 columnA에 의해 columnB당신이 당신이 기대하는 결과를 얻을 수 있습니다?
Andrew Piliser

2
@ johndoe 나는 그것이 필요할 것이라고 생각하지 않지만 매우 편리 할 수 ​​있습니다. 상점의 재고가 월간 예상 판매량의 5 %보다 낮을 수 없다는 제한 조건을 적용하려고한다고 가정하십시오. 또는 각 부서의 총 예산이 총 예산의 20 %를 넘지 않아야합니다. 동일한 데이터베이스를 사용하는 여러 응용 프로그램에서 동일한 방식으로 계산하려는 계산 열에도 나타날 수 있습니다.
Andrew Piliser

2
SQLite는이 있음을 지적 그것의 가치가 없는 열마다 미리 정의 된 유형을 설정 : "SQLite는은"유형이없는 "관계없이 해당 열의 선언 된 데이터 유형, 당신은 모든 테이블의 모든 열에서 원하는 모든 종류의 데이터를 저장할 수있는이 수단.. "
Prime

답변:


50

SQL정적으로 유형이 지정된 언어입니다. 즉, 변수를 사용하기 전에 변수 (또는이 경우 필드)의 유형을 알아야합니다. 동적 타입 언어와는 정반대이며, 반드시 그런 것은 아닙니다.

기본적으로 SQL은 관계형 데이터베이스 엔진 에서 데이터 ( DDL ) 및 액세스 데이터 ( DML ) 를 정의하도록 설계되었습니다 . 정적 타이핑은이 유형의 시스템에 대한 동적 타이핑에 비해 몇 가지 이점을 제공합니다.

  • 특정 레코드에 빠르게 액세스하는 데 사용되는 인덱스 는 크기가 고정되어 있으면 실제로 잘 작동합니다. 여러 필드를 가진 인덱스를 사용하는 쿼리를 고려하십시오. 데이터 유형과 크기를 미리 알고 있으면 인덱스의 값과 조건 자 (WHERE 절 또는 JOIN 기준)를 매우 빠르게 비교하고 원하는 레코드를 더 빨리 찾을 수 있습니다 .

  • 두 개의 정수 값을 고려하십시오 . 동적 유형 시스템에서는 가변 크기 일 수 있습니다 (Java BigInteger또는 Python의 내장 임의 정밀도 정수 라고 생각하십시오 ). 정수를 비교하려면 먼저 비트 길이를 알아야합니다. 이것은 현대 언어에 의해 대부분 숨겨져 있지만 CPU 수준에서는 매우 실제적인 정수 비교의 한 측면입니다. 크기가 미리 고정되어 있고 알려진 경우 전체 단계가 프로세스에서 제거됩니다. 다시 말하지만 데이터베이스는 가능한 한 빨리 많은 트랜잭션을 처리 할 수 ​​있어야합니다. 속도는 왕이다.

  • SQL은 1970 년대에 설계되었습니다. 초기의 마이크로 컴퓨팅에서 메모리는 최고였습니다. 데이터 제한은 스토리지 요구 사항을 확인하는 데 도움이되었습니다. 정수가 1 바이트를 넘지 않는 경우 왜 더 많은 스토리지를 할당합니까? 그것은 제한된 메모리 시대에 공간 낭비입니다. 현대에도 이러한 여분의 낭비 된 바이트는 CPU 캐시의 성능을 향상시키고 죽일 수 있습니다. 이들은 작은 개발 환경뿐만 아니라 초당 수백 건의 트랜잭션을 처리 할 수있는 데이터베이스 엔진입니다.

  • 제한된 스토리지 라인을 따라 단일 레코드를 메모리의 단일 페이지에 맞추는 것이 도움이됩니다. 한 페이지를 넘으면 더 많은 페이지 누락과 더 느린 메모리 액세스가 있습니다. 최신 엔진에는이 문제를 줄 이도록 최적화되어 있지만 여전히 문제가 없습니다. 데이터의 크기를 적절하게 조정하면이 위험을 완화 할 수 있습니다.

  • 또한 현대에는 SQL을 사용하여 ORM 또는 ODBC 또는 다른 계층을 통해 다른 언어로 플러그인 할 수 있습니다 . 이러한 언어 중 일부에는 강력한 정적 유형이 필요한 규칙이 있습니다. 동적 형식 언어는 다른 방식보다 정적 형식을 쉽게 처리 할 수 ​​있으므로보다 엄격한 요구 사항을 따르는 것이 가장 좋습니다.

  • 위와 같이 데이터베이스 엔진은 성능을 위해 필요하기 때문에 SQL은 정적 입력을 지원합니다.

강력하게 형식화 되지 않은 SQL 구현이 있다는 점은 흥미 롭습니다 . SQLite 는 아마도 이러한 관계형 데이터베이스 엔진의 가장 보편적 인 예일 것입니다. 다시 한 번, 단일 시스템에서 단일 스레드로 사용하도록 설계되었으므로 분당 수백만 건의 요청을 처리하는 엔터프라이즈 Oracle 데이터베이스와 같이 성능 문제가 두드러지지 않을 수 있습니다.


SQLite는 숫자 및 문자 데이터를 구별 할 데이터 유형을 가지고 있지만 데이터 저장의 5 "클래스"가 있습니다 sqlite.org/datatype3.html
FrustratedWithFormsDesigner

1
@FrustratedWithFormsDesigner 알고 있지만 SQL Server, Oracle 또는 PostgreSQL과 같은 엔진만큼 엄격하지는 않습니다.

검사 제한 조건의 존재로 인해 SQL은 정적으로 유형화 될뿐만 아니라 구체화 유형을 효과적으로 지원합니다.
gardenhead

4
첫 번째 글 머리 기호에 암시되어 있지만 Indexes더 기본적으로 다음과 같이 언급했습니다. 데이터 유형을 사용하면 데이터베이스 엔진 이 데이터를 이해 하고 비교할 수 있습니다 (더 큰 / 작은 숫자, 이전 / 이후 날짜 시간, 알파벳 전후). 따라서 정렬 및 쿼리가 가능합니다 .
Basil Bourque

따라서 크기가 중요하고 SQL이 사전에 알아야하는 경우 "Zillion"트랜잭션의 정확한 크기는 얼마입니까?
WernerCD

24

첫째 : 일반 텍스트는 이진입니다 (UTF8 또는 ASCII 문자 "0"및 "1"이 아니라 실제 켜기 / 끄기 비트 임)

즉, 몇 가지 이유는 다음과 같습니다.

  • 비즈니스 / 디자인 제약 : PERSON 테이블의 HEIGHT 열에 숫자 7626355112를 허용하는 것은 잘못되었습니다. INVOICE의 DATE 열에 "Howya"를 허용하는 것은 잘못되었습니다.
  • 오류 발생 가능성이 적은 코드 : 날짜 열에서 검색된 데이터가 실제로 날짜인지 확인하기 위해 코드를 작성할 필요가 없습니다. 열 유형이 동적 인 경우 열을 읽을 때 많은 유형을 확인해야합니다.
  • 컴퓨팅 효율성 : 열이 INTEGER 유형이고 SUM () 인 경우 RDBMS는 부동 소수점 산술을 적용 할 필요가 없습니다.
  • 스토리지 효율성 : 열이 VARCHAR (10)임을 나타내면 RDBMS가 공간을보다 정확하게 할당 할 수 있습니다.
  • 참조 무결성 및 단일성 : 부동 소수점 동등성이 까다롭기 때문에 테이블의 PK (또는 FK)는 부동 소수점을 허용하지 않아야하므로 문자 나 정수와 같이 부동 소수점이 아닌 유형으로 선언해야합니다.
  • 동적 (엄격하지 않은) 열 유형 (SQLite)과 함께 RDBMS가 있습니다 . "유형 선호도"라는 개념을 사용하면서도 불평없이 거의 모든 열에 아무 것도 삽입 할 수 있습니다. 여기서 논의하지 않을 절충 사항이 있습니다. 이 질문을 참조하십시오 .

8

데이터베이스가 작성된 기본 코드가 고정 크기 레코드를 할당하고 사용할 수 있도록하기 위해 특정 필드에 0-256 자의 텍스트가 포함될 수 있다는 것을 알고 있으면 256 바이트 블록을 할당하여 저장할 수 있습니다.

주어진 필드가 항상 레코드에서 x 바이트를 시작하거나 해당 필드에서 선택하면 각 레코드에서 x 바이트를 항상 검사한다는 것을 알고 있기 때문에 사용자 유형으로 추가 스토리지를 할당 할 필요가 없습니다.


모든 대답 만이 간결하고 요점 만 될 수 있다면 ...
Darren Ringer

6

데이터베이스의 열에 정의 된 유형이 제공 될 때 유형은 일반적으로 비트 단위의 특정 크기를 갖도록 자체 정의됩니다. 결과적으로 :

1) 데이터베이스 엔진이 테이블의 행을 순회 할 때 각 레코드가 끝나는 위치를 결정하기 위해 멋진 구문 분석을 수행 할 필요가 없으며 각 행이 32 바이트로 구성되어 있음을 알 수 있습니다. 다음 레코드는 현재 레코드 위치에 32 바이트를 추가하는 것으로 충분합니다.

2) 행 내에서 필드를 찾을 때 아무것도 구문 분석하지 않고 해당 필드에 대한 정확한 오프셋을 다시 알 수 있으므로 열 조회는 잠재적으로 비용이 많이 드는 데이터 처리 작업이 아닌 간단한 산술 연산입니다.


고정 길이 필드는 일관된 레코드 길이와 필드 오프셋으로 인해 처리 효율성을 높일 수 있지만 가변 길이 필드는 레코드 길이와 필드 오프셋이 다를 수 있으므로 이러한 이점을 무효화 할 수 있습니다. 마찬가지로 레코드 수준 압축은 가변 길이 레코드를 생성하므로 지정된 레코드의 위치를 ​​간단히 계산할 수 없습니다.
Zenilogix

이것은 사실이며, 정확한 이유로 가변 길이 필드를 피하는 것이 일반적인 조언이었습니다. 큰 플레이어가 어떻게하는지 모르겠지만 엔진이 가변 너비 필드를 사용자가 볼 수없는 테이블이나 메모리 블록에 저장하여 고정 길이의 이점을 되 찾을 수있는 것처럼 보입니다. 해당 필드의 기본 테이블 표현은 고정 된 너비의 '포인터'입니다. 우선 가변 길이 필드의 전체 스캔을 정기적으로 수행해야한다는 것을 고려할 때 간접적 성능 적중은 고정 너비를 유지하는 것이 좋습니다.
UserNotFound

3

DBMS에 정적 데이터 유형이있는 이유를 물었습니다 .

  1. 조회 속도. DBMS의 핵심은 프로그램에로드 할 수있는 것보다 훨씬 많은 데이터를 저장하는 것입니다. "지난 10 년 동안 세계에서 생성 된 모든 신용 카드 전표"를 생각하십시오. 이러한 데이터를 효율적으로 검색하려면 고정 길이 데이터 유형이 도움이됩니다. 날짜 스탬프 및 계좌 번호와 같은 구조화 된 데이터의 경우 특히 그렇습니다. 미리 다루고있는 것을 아는 경우 효율적인 색인에 쉽게로드 할 수 있습니다.

  2. 무결성과 제약. 고정 된 데이터 유형이있는 경우 데이터를 깨끗하게 유지하는 것이 더 쉽습니다.

  3. 역사. RDBMS는 컴퓨터에 몇 메가 바이트의 RAM이 있었을 때 시작되었으며 테라 바이트 규모의 스토리지는 엄청나게 비쌌습니다. 이러한 상황에서 테이블의 각 행에 12 바이트를 저장하면 수천 달러와 시간을 절약 할 수 있습니다.

  4. 고객층의 저주. 오늘날의 RDBMS는 매우 복잡하고 최적화 된 소프트웨어 패키지이며 수십 년 동안 축적 된 데이터를 사용하고 있습니다. 그들은 성숙합니다. 그들은 작동합니다. 오늘날 대규모 데이터 손실을 초래하는 RDBMS 충돌은 거의 발생하지 않습니다. 보다 유연한 데이터 타이핑 시스템을 사용하여 무언가로 전환하는 것은 대부분의 조직에 비용이나 위험이 없습니다.

비유 : 도시 지하철 시스템이 더 좁은 레일 게이지에서 더 조용하고, 더 조용하고, 더 효율적으로 작동한다는 것은 맹목적으로 명백 할 수 있습니다. 그러나 이러한 개선을 실현하기 위해 뉴욕시 지하철 시스템의 모든 레일을 어떻게 변경 하시겠습니까? 당신은 아니기 때문에 당신이 가진 것을 최적화합니다.


3

일반적으로 데이터베이스에 저장 대상에 대해 자세하게 설명할수록 디스크에 할당 할 공간 또는 검색 할 때 할당 할 메모리 양과 같이 해당 데이터와 관련된 다양한 성능 메트릭을 최적화 할 수 있습니다. .

왜 중간 텍스트, 긴 텍스트 및 텍스트입니까?

어떤 데이터베이스를 사용하는지 확실하지 않으므로 추측해야합니다.이 두 데이터 유형 중 하나에는 상한이 있지만 그중 하나는 그렇지 않습니다. 상한이있는 텍스트에 데이터 유형을 사용하면 데이터베이스에 각 레코드에 필요한 저장 공간이 얼마인지 알 수 있습니다. 또한 일부 데이터베이스에는 큰 (아마도 무제한) 텍스트와 작은 고정 길이 텍스트를 저장하는 방법이 다를 수 있습니다 (데이터베이스에 따라 다를 수 있으므로 설명서를 확인하여 자신의 정보를 확인하십시오).

왜 소수, 부동 및 정수입니까?

다른 수준의 정밀도는 다른 양의 저장 공간을 필요로하며 모든 사용에 높은 수준의 정밀도가 필요한 것은 아닙니다. 예를 들어 여기를 참조하십시오 : https://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements001.htm#SQLRF50950

오라클은 표현할 수있는 정밀도 수준과 숫자 크기 측면에서 스토리지 요구 사항과 기능이 다른 수많은 숫자 유형을 가지고 있습니다.


2

어느 정도는 역사적입니다.

옛날 옛적에, 테이블 형식의 데이터는 고정 길이 레코드로 구성된 파일에 미리 정의 된 필드로 구성되어 주어진 필드가 항상 같은 유형이고 각 레코드에서 같은 장소에 있도록 저장되었습니다. 이는 프로세싱을 효율적으로 만들고 코딩의 복잡성을 제한했다.

이러한 파일에 인덱스를 추가하면 관계형 데이터베이스의 시작 부분이 있습니다.

관계형 데이터베이스가 발전함에 따라 가변 길이 텍스트 또는 이진 필드를 포함하여 더 많은 데이터 유형과 저장 옵션을 도입하기 시작했습니다. 그러나 이로 인해 가변 길이 레코드가 도입되었으며 계산 또는 필드를 통해 고정 된 오프셋을 통해 레코드를 일관되게 찾을 수 없었습니다. 어쨌든 오늘날 기계는 당시보다 훨씬 강력합니다.

때로는 북미 전화 번호의 경우 10 자리 숫자와 같은 비즈니스 로직을 적용하기 위해 필드의 특정 크기를 설정하는 것이 유용합니다. 많은 시간이 단지 약간의 컴퓨팅 레거시 일뿐입니다.


1

데이터베이스가 고정 크기의 레코드를 사용하는 경우 데이터베이스의 모든 레코드는 내용이 변경 되더라도 동일한 위치에 계속 적합합니다. 반대로 데이터베이스가 필드에 필요한 스토리지 양을 정확하게 사용하여 레코드를 저장하려고하면 Emma Smith의 이름을 Emma Johnson으로 변경하면 레코드가 현재 위치에 맞지 않을 수 있습니다. 충분한 공간이있는 위치로 레코드를 이동하면 새 위치를 반영하도록 레코드 위치를 추적하는 인덱스를 업데이트해야합니다.

이러한 업데이트와 관련된 비용을 줄이는 여러 가지 방법이 있습니다. 예를 들어, 시스템이 레코드 번호 및 데이터 위치 목록을 유지 보수하는 경우 레코드가 이동하면 해당 목록 만 업데이트해야합니다. 불행히도, 이러한 접근 방식은 여전히 ​​상당한 비용이 소요됩니다 (예 : 레코드 번호와 위치 간의 매핑을 유지하려면 레코드 검색시 주어진 레코드 번호와 관련된 데이터를 검색하기 위해 추가 단계가 필요합니다). 고정 된 크기의 레코드를 사용하면 비효율적 인 것처럼 보일 수 있지만 훨씬 간단 해집니다.


1

웹 개발자로하는 많은 일을 위해 "무엇보다"무슨 일이 일어나고 있는지 이해할 필요가 없습니다. 그러나 도움이 될 때가 있습니다.

데이터베이스에 "이 열의 항목에는 256 바이트의 일반 텍스트 데이터 만있을 것"이라는 이점이 있습니다. 또는 "이 열에는 최대 16,777,215 바이트의 텍스트 항목이있을 수 있습니다"?

당신이 생각하는 것처럼, 그 이유는 효율성과 관련이 있습니다. 추상화 누출 . SELECT author FROM books테이블에있는 모든 필드의 크기를 알고있는 경우 와 같은 쿼리 가 매우 빠르게 실행될 수 있습니다.

Joel이 말했듯이

관계형 데이터베이스는 어떻게 구현 SELECT author FROM books됩니까? 관계형 데이터베이스에서 테이블의 모든 행 (예 : 책 테이블)은 정확히 같은 길이 (바이트)이며 모든 필드는 항상 행의 시작 부분으로부터 고정 된 오프셋에 있습니다. 예를 들어, books 테이블의 각 레코드 길이가 100 바이트이고 author 필드의 오프셋이 23이면 바이트 23, 123, 223, 323 등에 작성자가 저장됩니다. 이동할 코드는 무엇입니까? 이 쿼리 결과의 다음 레코드? 기본적으로 다음과 같습니다.

pointer += 100;

하나의 CPU 명령. 좋아.

많은 시간, 당신은 당신이 그것에 대해 걱정할 필요가없는 뻔뻔스러운 토대에서 멀리 떨어져서 일하고 있습니다. PHP 기반 웹 개발자로서 코드에서 사용하는 CPU 명령어 수에 관심이 있습니까? 대부분의 경우, 실제로는 아닙니다. 그러나 때로는 다음 두 가지 이유로 아는 것이 유용합니다. 라이브러리에서 내린 결정을 설명 할 수 있습니다. 때로는 자신의 코드에서 속도를 걱정해야합니다.

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