매우 큰 데이터베이스 파일이있는 sqlite의 성능 특성은 무엇입니까? [닫은]


325

sqlite는 지원되는 경우에도 매우 큰 데이터베이스 파일에서 잘 수행되지 않는다는 것을 알고 있습니다 (1GB 이상의 파일 크기가 필요한 경우 엔터프라이즈 rdbms 사용을 고려할 수 있음을 나타내는 sqlite 웹 사이트에 대한 의견이 있었음). 더 이상 찾지 못하면 sqlite의 이전 버전과 관련이있을 수 있습니다).

그러나 내 목적을 위해 다른 솔루션을 고려하기 전에 실제로 얼마나 나쁜지에 대한 아이디어를 얻고 싶습니다.

2GB부터 멀티 기가 바이트 범위의 sqlite 데이터 파일에 대해 이야기하고 있습니다. 누구든지 이것에 대해 경험이 있습니까? 팁 / 아이디어?


1
스레딩 (스레드 당 연결)을 사용하면 읽기에만 도움이 될 수 있습니다.- stackoverflow.com
a


23
2016 년 : SQLite에서 문제없이 실행되는 5GB 데이터베이스가 있습니다. Postgres에 정확히 동일한 데이터 세트를 설치했습니다. SQLite는 2.7ms, Postgres는 2.5ms에서 복잡한 쿼리를 실행했습니다. 더 쉬운 Regex 액세스 및 더 나은 색인 기능을 위해 Postgres를 사용했습니다. 그러나 나는 SQLite에 깊은 인상을 받았으며 그것을 사용할 수도있었습니다.
Paulb

답변:


246

그래서 매우 큰 파일에 대해 sqlite로 몇 가지 테스트를 수행하고 결론을 얻었습니다 (적어도 특정 응용 프로그램에 대해서는).

테스트에는 단일 테이블 또는 여러 테이블이있는 단일 sqlite 파일이 포함됩니다. 각 테이블에는 약 8 개의 열, 거의 모든 정수 및 4 개의 인덱스가 있습니다.

아이디어는 sqlite 파일이 약 50GB가 될 때까지 충분한 데이터를 삽입하는 것이 었습니다.

싱글 테이블

하나의 테이블로 sqlite 파일에 여러 행을 삽입하려고했습니다. 파일이 약 7GB 였을 때 (죄송합니다. 행 수를 구체적으로 지정할 수는 없습니다) 삽입 시간이 너무 오래 걸렸습니다. 모든 데이터를 삽입하는 테스트에 24 시간 정도 소요될 것으로 예상했지만 48 시간이 지나도 완료되지 않았습니다.

이것은 매우 큰 단일 sqlite 테이블에 삽입 및 다른 작업에도 문제가 있다는 결론을 내립니다.

테이블이 커지면 모든 인덱스를 삽입하고 업데이트하는 데 시간이 오래 걸리기 때문에 이것이 놀라운 일이 아닙니다.

여러 테이블

그런 다음 하루에 한 테이블 씩 여러 테이블에서 시간별로 데이터를 분할하려고했습니다. 원본 1 테이블의 데이터는 ~ 700 테이블로 분할되었습니다.

이 설정은 삽입에 문제가 없었으며 매일 새 테이블이 만들어 지므로 시간이 지날수록 시간이 오래 걸리지 않았습니다.

진공 문제

i_like_caffeine이 지적한 바와 같이 VACUUM 명령은 sqlite 파일이 클수록 문제가됩니다. 더 많은 삽입 / 삭제가 수행되면 디스크에서 파일 조각화가 더 나빠 지므로 파일을 최적화하고 파일 공간을 복구하기 위해 주기적으로 VACUUM을 사용하는 것이 목표입니다.

그러나 documentation 에서 지적했듯이 데이터베이스의 전체 사본은 진공을 수행하기 위해 만들어지며 완료하는 데 시간이 오래 걸립니다. 따라서 데이터베이스가 작을수록이 작업이 더 빨리 완료됩니다.

결론

특정 응용 프로그램의 경우 진공 성능과 삽입 / 삭제 속도를 모두 극대화하기 위해 하루에 하나씩 여러 db 파일로 데이터를 분할 할 것입니다.

이로 인해 쿼리가 복잡해 지지만 많은 양의 데이터를 인덱싱 할 수 있다는 점에서 가치가 있습니다. 또 다른 장점은 전체 db 파일을 삭제하여 하루의 가치있는 데이터 (응용 프로그램의 일반적인 작업)를 삭제할 수 있다는 것입니다.

속도가 문제가 될 때를 확인하기 위해 파일 당 테이블 크기를 모니터링해야 할 것입니다.

자동 진공 이외의 증분 진공 방법이없는 것 같습니다 . 진공 청소기의 목표는 자동 진공 청소기가하지 않는 파일 조각 모음 (파일 공간이별로 중요하지 않음)이기 때문에 사용할 수 없습니다. 실제로 문서화에 따르면 조각화가 더 심해질 수 있으므로 파일을 주기적으로 완전히 진공 청소기로 청소해야합니다.


5
매우 유용한 정보. 순수한 추측이지만 새로운 백업 API를 사용하여 매일 조각화되지 않은 데이터베이스 버전을 생성하고 VACUUM을 실행할 필요가 없는지 궁금합니다.
eodonohoe

24
궁금합니다. 모든 인서트가 거래에 포함 되었습니까?
Paul Lefebvre

9
예, 삽입은 트랜잭션 당 10000 개의 메시지 일괄 처리로 수행되었습니다.
Snazzer 2016 년

6
어떤 파일 시스템을 사용하셨습니까? ext {2,3,4} 인 경우 data = 설정은 무엇이며 저널링이 활성화 되었습니까? io 패턴 외에도 sqlite가 디스크로 플러시되는 방식이 중요 할 수 있습니다.
Tobu

5
나는 주로 Windows에서 테스트하고 있었으므로 Linux의 동작에 대해서는 언급 할 수 없습니다.
Snazzer

169

플랫폼에서 50GB 이상의 DBS를 사용하고 있습니다. 불평이 잘 작동하지 않습니다. 모든 것을 올바르게하고 있는지 확인하십시오! 사전 정의 된 명령문을 사용하고 있습니까? * SQLITE 3.7.3

  1. 업무
  2. 사전 진술
  3. 이 설정을 적용하십시오 (DB를 생성 한 직후)

    PRAGMA main.page_size = 4096;
    PRAGMA main.cache_size=10000;
    PRAGMA main.locking_mode=EXCLUSIVE;
    PRAGMA main.synchronous=NORMAL;
    PRAGMA main.journal_mode=WAL;
    PRAGMA main.cache_size=5000;
    

이것이 다른 사람들을 도울 수 있기를 바랍니다.


22
최근 160GB 범위의 DB로 테스트되었으며 훌륭하게 작동합니다.
Snazzer

10
또한 PRAGMA main.temp_store = MEMORY;.
Vikrant Chaudhary

40
@Alex, 왜 PRAGMA main.cache_size = 5000; 두 개가 있습니까?
Jack

23
이러한 최적화를 맹목적으로 적용하지 마십시오. 특히 synchronous = NORMAL은 충돌에 안전하지 않습니다. 즉, 적시에 프로세스가 충돌하면 디스크 오류가 없어도 데이터베이스가 손상 될 수 있습니다. sqlite.org/pragma.html#pragma_synchronous
mpm

22
@Alex 그 값과 기본 값과 기본값의 차이점을 설명해 주시겠습니까?
4m1nh4j1

65

눈에 띄는 성능 문제없이 최대 3.5GB 크기의 SQLite 데이터베이스를 만들었습니다. 올바르게 기억한다면 SQLite2에 약간의 한계가 있다고 생각하지만 SQLite3에 그러한 문제가 있다고 생각하지 않습니다.

SQLite Limits 페이지 에 따르면 각 데이터베이스 페이지의 최대 크기는 32K입니다. 데이터베이스의 최대 페이지는 1024 ^ 3입니다. 내 수학에 따르면 최대 크기는 32TB입니다. SQLite에 도달하기 전에 파일 시스템의 한계에 도달 할 것이라고 생각합니다!


3
당신이 프랑스어를 눌러의 좋은 냄비를 양조 할 수있는 8 세대 sqlite가 데이터베이스에 3000 개 행을 삭제하려고 당신이 수행하는 어떤 작업에 따라, 롤, 충분한 시간을 소요
benjaminz

4
@benjaminz, 당신은 그것을 잘못하고 있어야합니다. 하나의 트랜잭션에서 3k 행의 삭제를 래핑하면 거의 즉각적입니다. 10k 행을 하나씩 삭제하는 데 30 분이 걸렸습니다. 그러나 일단 모든 삭제 문을 하나의 트랜잭션으로 래핑하면 5 초가 걸렸습니다.
mvp

55

인서트를 수행하는 데 48 시간 이상이 걸리는 많은 이유는 색인 때문입니다. 다음보다 훨씬 빠릅니다.

1-모든 인덱스 삭제 2-모든 인서트 수행 3-인덱스 다시 작성


23
잘 알려져 있지만 ... 오래 진행되는 프로세스의 경우 인덱스를 다시 작성하기 위해 인덱스를 정기적으로 삭제하지는 않습니다. 특히 작업을 위해 쿼리하려고 할 때 특히 그렇습니다. sqlite db를 처음부터 다시 작성해야 할 때 모든 삽입 작업이 완료된 후에 인덱스가 작성되는 방식입니다.
Snazzer

24
비슷한 상황에서 @Snazzer는 "누적 기"테이블을 사용했습니다. 하루에 한 번 누적 된 행을 단일 트랜잭션 내에서 누산기 테이블에서 기본 테이블로 이동합니다. 필요한 경우보기에서 두 테이블을 단일 테이블로 표시했습니다.
CAFxX

4
다른 옵션은 인덱스를 유지하지만 삽입하기 전에 데이터를 인덱스 순서로 사전 정렬하는 것입니다.
Steven Kryskalla

1
@StevenKryskalla 인덱스를 삭제하고 다시 만드는 것과 어떻게 비교됩니까? 벤치마킹 한 링크가 있습니까?
mcmillab

1
@mcmillab 이것은 몇 년 전이므로 모든 세부 사항이나 벤치 마크 통계를 기억하지 못하지만 직관적으로 생각하면 무작위로 정렬 된 N 개의 요소를 색인에 삽입하면 O (NlogN) 시간이 걸리고 N 개의 정렬 된 요소를 삽입하면 O (N ) 시각.
Steven Kryskalla 19

34

일반적인 권장 사항 외에 :

  1. 대량 삽입을위한 낙하 지수.
  2. 대규모 트랜잭션에서 일괄 삽입 / 업데이트.
  3. 버퍼 캐시 / 비활성화 저널 / w PRAGMA를 조정하십시오.
  4. 많은 캐시 ™를 사용할 수 있도록 64 비트 시스템을 사용하십시오.
  5. [2014 년 7 월 추가] 여러 SQL 쿼리를 실행하는 대신 CTE (공통 테이블 식) 를 사용하십시오 ! SQLite 릴리스 3.8.3이 필요합니다.

SQLite3에 대한 경험을 통해 다음을 배웠습니다.

  1. 삽입 속도를 극대화하려면 열 제약 조건이있는 스키마를 사용하지 마십시오. (필요에 따라 테이블을 나중에 변경 ALTER TABLE을 사용하여 제약 조건을 추가 할 수 없습니다).
  2. 필요한 것을 저장하도록 스키마를 최적화하십시오. 때때로 이것은 데이터베이스에 삽입하기 전에 테이블을 분해하거나 데이터를 압축 / 변환하는 것을 의미합니다. 좋은 예는 IP 주소를 (긴) 정수로 저장하는 것입니다.
  3. 잠금 경합을 최소화하기 위해 db 파일 당 하나의 테이블. 단일 연결 개체를 원할 경우 ATTACH DATABASE를 사용하십시오 .
  4. SQLite는 다양한 유형의 데이터를 동일한 열 (동적 타이핑)에 저장할 수 있으므로이를 활용하십시오.

질문 / 의견을 환영합니다. ;-)


1
'DB 파일 당 하나의 테이블'에서 어느 정도의 영향을 받습니까? 흥미로운 것 같습니다. 테이블에 3 개의 테이블 만 있고 처음부터 작성되는 경우 중요하다고 생각하십니까?
Martin Velez

4
@martin은 말하기 싫어하지만 그 대답은 달려 있습니다. 아이디어는 데이터를 관리 가능한 크기로 분할하는 것입니다. 내 유스 케이스에서는 다른 호스트에서 데이터를 수집하고 사실 후에 데이터를보고 하므로이 접근법은 잘 작동했습니다. 다른 사람들이 제안한 날짜 / 시간별 파티션은 내가 상상할 수있는 오랜 기간에 걸친 데이터에 잘 작동해야합니다.
Lester Cheung

3
@Lester Cheung : 두 번째 # 1과 관련하여 : 오늘날까지 SQLite3은 테이블 생성 후 ALTER TABLE을 사용하여 제약 조건을 추가하는 것을 지원하지 않습니다. 기존 테이블 행에서 제한 조건을 추가하거나 제거하는 유일한 방법은 원하는 특성을 가진 새 테이블을 작성하고 모든 행을 복사하는 것입니다. 이는 제한 조건으로 한 번 삽입하는 것보다 훨씬 느릴 수 있습니다.
Mumbleskates

3
@Widdershins 당신은 절대적으로 맞습니다-SQLite의 ALTER TABLE은 제약 조건을 추가 할 수 없습니다. 나는 내가 무엇을 흡연하고 있었는지 모르겠다-답변을 업데이트 할 것입니다-감사합니다.
Lester Cheung

이러한 제안 중 어느 것도 엄청난 SQLite DB 파일 사용과 관련이 없습니다. 이 답변이 제출 된 이후 질문이 편집 되었습니까?
A. Rager

9

sqlite 스케일링에 대한 주요 불만은 다음과 같습니다.

  1. 단일 프로세스 쓰기
  2. 미러링이 없습니다.
  3. 복제가 없습니다.

9

7GB SQLite 데이터베이스가 있습니다. 내부 조인으로 특정 쿼리를 수행하려면 2.6 초가 걸립니다.이 속도를 높이기 위해 인덱스 추가를 시도했습니다. 어떤 인덱스를 추가했는지에 따라 때로는 쿼리가 0.1로 내려 갔고 때로는 7까지 올라갔습니다. 필자의 경우 문제는 열이 많이 복제 된 경우 색인을 추가하면 성능이 저하된다는 것입니다.


9
중복이 많은 열이 성능을 저하시키는 이유는 무엇입니까 (심각한 질문)?
Martin Velez

6
카디널리티가 낮은 열은 인덱스하기가 더 어렵습니다. stackoverflow.com/questions/2113181/…
metrix

9

SQLite 문서에는 데이터베이스 파일의 실제 크기 제한이 수십 GB : s라는 진술이있었습니다. 트랜잭션을 시작할 때마다 SQLite가 "더티 페이지의 비트 맵을 할당"해야하기 때문입니다. 따라서 데이터베이스의 각 MB마다 256 바이트의 RAM이 필요했습니다. 50GB DB 파일에 삽입하려면 대용량 (2 ^ 8) * (2 ^ 10) = 2 ^ 18 = 256MB의 RAM이 필요합니다.

그러나 최신 버전의 SQLite에서는 더 이상 필요하지 않습니다. 자세한 내용은 여기를 참조 하십시오 .


25
나는이 밖으로을 지적해야 할 매우 죄송하지만, 2^18256 K. 사실입니다
가브리엘 슈라이버는

7
@GabrielSchreiber 그리고 50GB가 (2 ^ 10) MB가 아니라는 사실은 1GB에 불과합니다. 따라서 50GB 데이터베이스의 경우 12.5MB의 메모리가 필요합니다. (2 ^ 8) * (2 ^ 10) * 50
elipoultorak

8

vacuum 명령을 사용할 때 큰 sqlite 파일에 문제가 발생했습니다.

auto_vacuum 기능을 아직 시도하지 않았습니다. 데이터를 자주 업데이트하고 삭제할 것으로 예상되는 경우 살펴볼 가치가 있습니다.

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