SQLite의 제한 사항

SQLite의 제한 사항 (Limits In SQLite)

이 문서에서 "제한(limits)"은 초과할 수 없는 크기나 수량을 의미해요. 우리가 관심을 갖는 것은 BLOB의 최대 바이트 수나 테이블의 최대 컬럼 수 같은 것들이에요.

출처: Limits In SQLite

본문

SQLite는 원래 임의의 제한을 피하는 정책으로 설계되었어요. 물론 유한한 메모리와 디스크 공간을 가진 머신에서 실행되는 모든 프로그램에는 어떤 종류의 제한이 있어요. 하지만 SQLite에서는 그 제한들이 잘 정의되어 있지 않았어요. 정책은 메모리에 들어가고 32비트 정수로 셀 수 있다면 작동해야 한다는 것이었어요.

안타깝게도 제한 없는 정책이 문제를 만든다는 것이 드러났어요. 상한이 잘 정의되어 있지 않아 테스트되지 않았고, SQLite를 극한으로 밀어붙일 때 버그가 자주 발견되었어요. 이런 이유로 약 3.5.8 (2008-04-16) 릴리스 이후의 SQLite 버전은 잘 정의된 제한을 가지며, 그 제한들은 테스트 스위트 (test suite)의 일부로 테스트돼요.

이 문서는 SQLite의 제한이 무엇인지, 그리고 특정 애플리케이션에 대해 어떻게 맞춤화할 수 있는지 정의해요. 제한의 기본 설정은 보통 상당히 크고 거의 모든 애플리케이션에 충분해요. 어떤 애플리케이션은 여기저기서 제한을 높이기를 원할 수도 있지만, 우리는 그런 요구는 드물 것이라고 예상해요. 더 흔하게는 애플리케이션이 더 높은 수준의 SQL 문 생성기의 버그가 발생할 때 과도한 리소스 사용을 피하거나 악성 SQL 문을 주입하는 공격자를 막기 위해 SQLite를 훨씬 낮은 제한으로 다시 컴파일하기를 원할 수도 있어요.

일부 제한은 limit categories 중 하나와 함께 sqlite3_limit() 인터페이스를 사용해 연결(connection) 단위로 런타임에 변경할 수 있어요. 런타임 제한은 여러 데이터베이스를 가진 애플리케이션(일부는 내부 전용이고, 다른 일부는 잠재적으로 적대적인 외부 에이전트의 영향을 받거나 제어될 수 있는)을 위해 설계되었어요. 예를 들어 웹 브라우저 애플리케이션은 과거 페이지 뷰를 추적하기 위해 내부 데이터베이스를 사용하지만, 인터넷에서 다운로드된 javascript 애플리케이션이 만들고 제어하는 하나 이상의 별도 데이터베이스를 가질 수 있어요. sqlite3_limit() 인터페이스는 신뢰할 수 있는 코드가 관리하는 내부 데이터베이스는 제한 없이 두면서, 동시에 서비스 거부 공격을 막기 위해 신뢰할 수 없는 외부 코드가 만들거나 제어하는 데이터베이스에는 엄격한 제한을 두는 것을 허용해요.

1. 문자열 또는 BLOB의 최대 길이 (Maximum length of a string or BLOB)

SQLite에서 문자열 또는 BLOB의 최대 바이트 수는 전처리기 매크로 SQLITE_MAX_LENGTH로 정의돼요. 이 매크로의 기본값은 10억 (1 thousand million 또는 1,000,000,000)이에요. 컴파일 타임에 다음과 같은 명령줄 옵션을 사용해 이 값을 올리거나 내릴 수 있어요:

-DSQLITE_MAX_LENGTH=123456789

현재 구현은 최대 231-3 또는 2147483645까지의 문자열 또는 BLOB 길이만 지원해요. 그리고 hex() 같은 일부 내장 함수는 그 지점 훨씬 전에 실패할 수 있어요. 보안에 민감한 애플리케이션에서는 최대 문자열 및 BLOB 길이를 늘리려고 하지 않는 것이 좋아요. 사실 가능하다면 최대 문자열 및 BLOB 길이를 수백만 정도의 범위의 무언가로 낮추는 것이 좋을 수도 있어요.

SQLite의 INSERT와 SELECT 처리의 일부 동안 데이터베이스의 각 행의 완전한 내용이 단일 BLOB으로 인코딩돼요. 그래서 SQLITE_MAX_LENGTH 매개변수는 행의 최대 바이트 수도 결정해요.

최대 문자열 또는 BLOB 길이는 sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size) 인터페이스를 사용해 런타임에 낮출 수 있어요.

2. 최대 컬럼 수 (Maximum Number Of Columns)

SQLITE_MAX_COLUMN 컴파일 타임 매개변수는 다음에 대한 상한을 설정하는 데 사용돼요:

  • 테이블의 컬럼 수
  • 인덱스의 컬럼 수
  • 뷰의 컬럼 수
  • UPDATE 문의 SET 절의 항 수
  • SELECT 문의 결과 집합의 컬럼 수
  • GROUP BY 또는 ORDER BY 절의 항 수
  • INSERT 문의 값 수

SQLITE_MAX_COLUMN의 기본 설정은 2000이에요. 컴파일 타임에 최대 32767까지의 값으로 변경할 수 있어요. 반면 많은 경험 많은 데이터베이스 설계자들은 잘 정규화된 데이터베이스는 테이블에 100개 이상의 컬럼을 필요로 하지 않을 것이라고 주장할 거예요.

대부분의 애플리케이션에서 컬럼 수는 적어요 - 수십 개 정도예요. SQLite 코드 생성기에는 N이 컬럼 수인 O(N²) 알고리즘을 사용하는 곳이 있어요. 그래서 SQLITE_MAX_COLUMN을 정말 큰 숫자로 다시 정의하고 많은 컬럼을 사용하는 SQL을 생성하면 sqlite3_prepare_v2()가 느리게 실행될 수 있어요.

최대 컬럼 수는 sqlite3_limit(db,SQLITE_LIMIT_COLUMN,size) 인터페이스를 사용해 런타임에 낮출 수 있어요.

3. SQL 문의 최대 길이 (Maximum Length Of An SQL Statement)

SQL 문 텍스트의 최대 바이트 수는 기본값이 1,000,000,000인 SQLITE_MAX_SQL_LENGTH로 제한돼요.

SQL 문이 백만 바이트 길이로 제한된다면, 당연히 INSERT 문 안에 리터럴로 임베딩해 수백만 바이트 문자열을 삽입할 수 없을 거예요. 하지만 어차피 그렇게 하면 안 돼요. 데이터에는 호스트 매개변수 (parameters)를 사용하세요. 다음과 같은 짧은 SQL 문을 준비해요:

INSERT INTO tab1 VALUES(?,?,?);

그런 다음 sqlite3_bind_XXXX() 함수를 사용해 큰 문자열 값을 SQL 문에 바인딩해요. 바인딩 사용은 문자열에서 따옴표 문자를 이스케이프할 필요를 없애서 SQL 주입 공격의 위험을 줄여요. 또한 큰 문자열을 많이 파싱하거나 복사할 필요가 없으므로 더 빠르게 실행돼요.

SQL 문의 최대 길이는 sqlite3_limit(db,SQLITE_LIMIT_SQL_LENGTH,size) 인터페이스를 사용해 런타임에 낮출 수 있어요.

4. 조인의 최대 테이블 수 (Maximum Number Of Tables In A Join)

SQLite는 64개보다 많은 테이블을 포함하는 조인을 지원하지 않아요. 이 제한은 SQLite 코드 생성기가 질의 최적화 프로그램에서 조인 테이블당 1비트의 비트맵을 사용한다는 사실에서 비롯돼요.

SQLite는 효율적인 질의 플래너 알고리즘 (query planner algorithm)을 사용하므로 큰 조인조차도 빠르게 준비(prepared)될 수 있어요. 따라서 조인의 테이블 수 제한을 올리거나 내리는 메커니즘은 없어요.

5. 표현식 트리의 최대 깊이 (Maximum Depth Of An Expression Tree)

SQLite는 처리를 위해 표현식을 트리로 파싱해요. 코드 생성 동안 SQLite는 이 트리를 재귀적으로 탐색해요. 따라서 스택 공간을 너무 많이 사용하는 것을 피하기 위해 표현식 트리의 깊이가 제한돼요.

SQLITE_MAX_EXPR_DEPTH 매개변수가 최대 표현식 트리 깊이를 결정해요. 값이 0이면 제한이 적용되지 않아요. 현재 구현은 기본값이 1000이에요.

SQLITE_MAX_EXPR_DEPTH가 처음에 양수이면 sqlite3_limit(db,SQLITE_LIMIT_EXPR_DEPTH,size) 인터페이스를 사용해 표현식 트리의 최대 깊이를 런타임에 낮출 수 있어요. 다시 말해, 표현식 깊이에 이미 컴파일 타임 제한이 있다면 최대 표현식 깊이를 런타임에 낮출 수 있어요. SQLITE_MAX_EXPR_DEPTH가 컴파일 타임에 0으로 설정되면 (표현식 깊이가 무제한이면), sqlite3_limit(db,SQLITE_LIMIT_EXPR_DEPTH,size)는 no-op이에요.

6. 함수의 최대 인자 수 (Maximum Number Of Arguments On A Function)

SQLITE_MAX_FUNCTION_ARG 매개변수는 SQL 함수에 전달될 수 있는 최대 매개변수 수를 결정해요. 수년 동안 기본값은 약 100이었지만, 기본값은 SQLite 버전 3.48.0 (2025-01-14)부터 1000으로 올라갔어요.

함수의 인자 수는 때때로 부호 있는 16비트 정수에 저장돼요. 그래서 SQLITE_MAX_FUNCTION_ARG에는 32767이라는 하드 상한이 있어요.

함수의 최대 인자 수는 sqlite3_limit(db,SQLITE_LIMIT_FUNCTION_ARG,size) 인터페이스를 사용해 런타임에 낮출 수 있어요.

7. 복합 SELECT 문의 최대 항 수 (Maximum Number Of Terms In A Compound SELECT Statement)

복합 SELECT 문은 UNION, UNION ALL, EXCEPT 또는 INTERSECT 연산자로 연결된 두 개 이상의 SELECT 문이에요. 복합 SELECT 안의 각 개별 SELECT 문을 "항(term)"이라고 불러요.

SQLite의 코드 생성기는 재귀 알고리즘을 사용해 복합 SELECT 문을 처리해요. 스택의 크기를 제한하기 위해 복합 SELECT의 항 수를 제한해요. 항의 최대 수는 기본값이 500인 SQLITE_MAX_COMPOUND_SELECT예요. 실제로 복합 select의 항 수가 한 자릿수를 초과하는 것을 거의 본 적이 없으므로 이는 넉넉한 배정이라고 생각해요.

복합 SELECT 항의 최대 수는 sqlite3_limit(db,SQLITE_LIMIT_COMPOUND_SELECT,size) 인터페이스를 사용해 런타임에 낮출 수 있어요.

8. LIKE 또는 GLOB 패턴의 최대 길이 (Maximum Length Of A LIKE Or GLOB Pattern)

SQLite의 기본 LIKEGLOB 구현에 사용되는 패턴 매칭 알고리즘은 특정 병리적(병적) 경우에 대해 O(N²) 성능(여기서 N은 패턴의 문자 수)을 보일 수 있어요. 자신의 LIKE 또는 GLOB 패턴을 지정할 수 있는 못된 사용자들의 서비스 거부 공격을 피하기 위해, LIKE 또는 GLOB 패턴의 길이는 SQLITE_MAX_LIKE_PATTERN_LENGTH 바이트로 제한돼요. 이 제한의 기본값은 50000이에요. 현대 워크스테이션은 병리적인 50000바이트의 LIKE 또는 GLOB 패턴조차도 상대적으로 빠르게 평가할 수 있어요. 서비스 거부 문제는 패턴 길이가 수백만 바이트가 될 때만 나타나요. 그럼에도 대부분의 유용한 LIKE 또는 GLOB 패턴은 길이가 기껏해야 수십 바이트이므로, 편집증적인 애플리케이션 개발자는 외부 사용자가 임의의 패턴을 생성할 수 있다는 것을 안다면 이 매개변수를 수백 정도의 범위로 줄이고 싶을 수도 있어요.

LIKE 또는 GLOB 패턴의 최대 길이는 sqlite3_limit(db,SQLITE_LIMIT_LIKE_PATTERN_LENGTH,size) 인터페이스를 사용해 런타임에 낮출 수 있어요.

9. 단일 SQL 문의 최대 호스트 매개변수 수 (Maximum Number Of Host Parameters In A Single SQL Statement)

호스트 매개변수 (parameter)sqlite3_bind_XXXX() 인터페이스 중 하나를 사용해 채워지는 SQL 문의 자리 표시자예요. 많은 SQL 프로그래머는 물음표("?")를 호스트 매개변수로 사용하는 것에 익숙해요. SQLite는 또한 ":", "$", "@"가 앞에 붙은 명명된 호스트 매개변수와 "?123" 형태의 번호가 붙은 호스트 매개변수를 지원해요.

SQLite 문의 각 호스트 매개변수에는 번호가 할당돼요. 번호는 보통 1로 시작하고 각각의 새 매개변수마다 1씩 증가해요. 하지만 "?123" 형태를 사용하면 호스트 매개변수 번호는 물음표 뒤에 오는 숫자예요.

SQLite는 1과 사용된 가장 큰 호스트 매개변수 번호 사이의 모든 호스트 매개변수를 담을 공간을 할당해요. 따라서 ?1000000000과 같은 호스트 매개변수를 포함하는 SQL 문은 기가바이트의 저장 공간을 요구할 거예요. 이는 호스트 머신의 리소스를 쉽게 압도할 수 있어요. 과도한 메모리 할당을 막기 위해 호스트 매개변수 번호의 최대 값은 SQLITE_MAX_VARIABLE_NUMBER이며, 이는 SQLite 3.32.0 (2020-05-22) 이전 버전에서는 기본값이 999이고, 3.32.0 이후 버전에서는 32766이에요.

최대 호스트 매개변수 번호는 sqlite3_limit(db,SQLITE_LIMIT_VARIABLE_NUMBER,size) 인터페이스를 사용해 런타임에 낮출 수 있어요.

10. 트리거 재귀의 최대 깊이 (Maximum Depth Of Trigger Recursion)

SQLite는 재귀적 트리거를 포함하는 문이 무제한의 메모리를 사용하는 것을 막기 위해 트리거의 재귀 깊이를 제한해요.

SQLite 버전 3.6.18 (2009-09-11) 이전에는 트리거가 재귀적이지 않아서 이 제한은 의미가 없었어요. 3.6.18부터 재귀적 트리거가 지원되지만 PRAGMA recursive_triggers 문을 사용해 명시적으로 활성화해야 해요. SQLITE_MAX_TRIGGER_DEPTH는 재귀적 트리거가 활성화된 경우에만 의미가 있어요.

기본 최대 트리거 재귀 깊이는 1000이에요.

11. 최대 부착 데이터베이스 수 (Maximum Number Of Attached Databases)

ATTACH 문은 두 개 이상의 데이터베이스를 같은 데이터베이스 연결에 연결하고 마치 하나의 데이터베이스인 것처럼 작동하게 하는 SQLite 확장이에요. 동시에 부착된 데이터베이스의 수는 기본 설정이 10인 SQLITE_MAX_ATTACHED로 제한돼요. 부착된 데이터베이스의 최대 수는 125를 넘어 증가시킬 수 없어요.

부착된 데이터베이스의 최대 수는 sqlite3_limit(db,SQLITE_LIMIT_ATTACHED,size) 인터페이스를 사용해 런타임에 낮출 수 있어요.

12. 데이터베이스 파일의 최대 페이지 수 (Maximum Number Of Pages In A Database File)

SQLite는 데이터베이스 파일이 너무 커져 과도한 디스크 공간을 소비하는 것을 막기 위해 데이터베이스 파일의 크기를 제한할 수 있어요. SQLITE_MAX_PAGE_COUNT 매개변수는 단일 데이터베이스 파일에 허용되는 최대 페이지 수예요. 데이터베이스 파일이 이보다 커지게 할 새 데이터를 삽입하려는 시도는 SQLITE_FULL을 반환해요.

SQLITE_MAX_PAGE_COUNT의 가장 큰 가능한 설정은 4294967294 (232-2)예요. 버전 3.45.0 (2024-01-15)부터 4294967294가 SQLITE_MAX_PAGE_COUNT의 기본값이기도 해요. 기본 페이지 크기 4096바이트와 함께 사용하면 최대 데이터베이스 크기는 약 17.5테라바이트가 돼요. 페이지 크기가 최대 65536바이트로 증가하면 데이터베이스 파일은 약 281테라바이트까지 커질 수 있어요.

max_page_count PRAGMA를 사용해 런타임에 이 제한을 올리거나 내릴 수 있어요.

13. 테이블의 최대 행 수 (Maximum Number Of Rows In A Table)

테이블의 이론적 최대 행 수는 264 (18446744073709551616 또는 약 1.8e+19)이에요. 최대 데이터베이스 크기 281테라바이트가 먼저 도달되므로 이 제한은 도달할 수 없어요. 281테라바이트 데이터베이스는 인덱스가 없고 각 행이 매우 적은 데이터를 포함하는 경우에만 약 2e+13 행 이하를 담을 수 있어요.

14. 최대 데이터베이스 크기 (Maximum Database Size)

모든 데이터베이스는 하나 이상의 "페이지"로 구성돼요. 단일 데이터베이스 내에서 모든 페이지는 같은 크기이지만, 다른 데이터베이스는 512에서 65536 사이(포함)의 2의 거듭제곱 페이지 크기를 가질 수 있어요. 데이터베이스 파일의 최대 크기는 4294967294 페이지예요. 최대 페이지 크기 65536바이트에서는 약 2.8e+14바이트 (281테라바이트, 또는 256에서 1테비바이트, 또는 281474기가바이트, 또는 262143기비바이트)의 최대 데이터베이스 크기로 환산돼요.

이 특정 상한은 개발자들이 이 제한에 도달할 수 있는 하드웨어에 접근할 수 없으므로 테스트되지 않았어요. 하지만 테스트는 데이터베이스가 기본 파일시스템의 최대 파일 크기(보통 이론적 최대 데이터베이스 크기보다 훨씬 작음)에 도달할 때와 데이터베이스가 디스크 공간 고갈로 커질 수 없을 때 SQLite가 올바르고 합리적으로 동작하는지 검증해요.

15. 스키마의 최대 테이블 수 (Maximum Number Of Tables In A Schema)

각 테이블과 인덱스는 데이터베이스 파일에 최소한 한 페이지를 요구해요. 따라서 데이터베이스 파일의 최대 페이지 수는 스키마의 테이블과 인덱스 수의 상한이기도 해요. 앞 문장에서 "인덱스(index)"는 CREATE INDEX 문을 사용해 명시적으로 만들어진 인덱스 또는 UNIQUE와 PRIMARY KEY 제약이 만든 암시적 인덱스를 의미해요.

데이터베이스가 열릴 때마다 전체 스키마가 스캔되고 파싱되며 스키마의 파스 트리가 메모리에 유지돼요. 이는 데이터베이스 연결 시작 시간과 초기 메모리 사용량이 스키마의 크기에 비례한다는 뜻이에요.

더 알아보기 (Learn more)