복붙노트

[SQL] 9000 만 개 기록을 처리 SQLite는 할 수 있습니까?

SQL

9000 만 개 기록을 처리 SQLite는 할 수 있습니까?

아니면 내가이 문제를 해결하기 위해 다른 망치를 사용해야합니다.

내가 SQLite는 데이터베이스에 저장하려고 한 데이터를 효과적으로 희소 행렬을 저장하기위한 매우 간단한 사용 사례를 가지고있다. 나는 테이블을 만들었습니다 :

create TABLE data ( id1 INTEGER KEY, timet INTEGER KEY, value REAL )

되는 I는 올해 (800 개 요소를 10 분 간격, 45 회), 대부분의 일을 많은 데이터를 삽입합니다. 의 튜플 (ID1, timet)는 항상 고유합니다.

timet 값은 시대 이후 초, 항상 증가한다. ID1은 모든 실제적인 목적으로, 임의의 정수이다. 아마 단지 20,000 고유 ID 불구하고있다.

나는 다음과 같이 어디 timet가 == 언젠가 모든 값 ID1 == someid 또는 액세스하는 모든 요소에 액세스하는 것입니다. 리눅스의 C 인터페이스를 통해 최신 SQLite는을 사용하여 내 시험에서이 중 하나에 대한 조회 (또는이 조회의 변형) 내 사용 사례에 대해 충분히 빨리하지 않은, 약 30 초 정도 걸립니다.

나는 데이터베이스에 대한 인덱스를 정의했지만,이 (내가 ... 잘못하지만 이런 짓을했을 수도) 완전히 쓸모없는 속도로 삽입을 둔화

모든 데이터에 대한 매우 느린 액세스 리드 위의 표. 내 질문은 :

SQL 내 아주 기본적인 이해를 용서하십시오!

감사

I 쇼가 삽입 속도가 감속 기어 방식으로 지표를 사용하는 코드 샘플을 포함한다. 장소에 '인덱스를 생성 명령문으로 코드를 완료하는 19 개의 분 정도 걸립니다. 그없이, 18 초 단위로 실행됩니다.

#include <iostream>
#include <sqlite3.h>

void checkdbres( int res, int expected, const std::string msg ) 
{
  if (res != expected) { std::cerr << msg << std::endl; exit(1); } 
}

int main(int argc, char **argv)
{
  const size_t nRecords = 800*45*30;

  sqlite3      *dbhandle = NULL;
  sqlite3_stmt *pStmt = NULL;
  char statement[512];

  checkdbres( sqlite3_open("/tmp/junk.db", &dbhandle ), SQLITE_OK, "Failed to open db");

  checkdbres( sqlite3_prepare_v2( dbhandle, "create table if not exists data ( issueid INTEGER KEY, time INTEGER KEY, value REAL);", -1, & pStmt, NULL ), SQLITE_OK, "Failed to build create statement");
  checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute insert statement" );
  checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize insert");
  checkdbres( sqlite3_prepare_v2( dbhandle, "create index issueidindex on data (issueid );", -1, & pStmt, NULL ), SQLITE_OK, "Failed to build create statement");
  checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute insert statement" );
  checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize insert");
  checkdbres( sqlite3_prepare_v2( dbhandle, "create index timeindex on data (time);", -1, & pStmt, NULL ), SQLITE_OK, "Failed to build create statement");
  checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute insert statement" );
  checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize insert");

  for ( size_t idx=0; idx < nRecords; ++idx)
  {
    if (idx%800==0)
    {
      checkdbres( sqlite3_prepare_v2( dbhandle, "BEGIN TRANSACTION", -1, & pStmt, NULL ), SQLITE_OK, "Failed to begin transaction");
      checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute begin transaction" );
      checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize begin transaction");
      std::cout << "idx " << idx << " of " << nRecords << std::endl;
    }

    const size_t time = idx/800;
    const size_t issueid = idx % 800;
    const float value = static_cast<float>(rand()) / RAND_MAX;
    sprintf( statement, "insert into data values (%d,%d,%f);", issueid, (int)time, value );
    checkdbres( sqlite3_prepare_v2( dbhandle, statement, -1, &pStmt, NULL ), SQLITE_OK, "Failed to build statement");
    checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute insert statement" );
    checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize insert");

    if (idx%800==799)
    {
      checkdbres( sqlite3_prepare_v2( dbhandle, "END TRANSACTION", -1, & pStmt, NULL ), SQLITE_OK, "Failed to end transaction");
      checkdbres( sqlite3_step( pStmt ), SQLITE_DONE, "Failed to execute end transaction" );
      checkdbres( sqlite3_finalize( pStmt ), SQLITE_OK, "Failed to finalize end transaction");
    }
  }

  checkdbres( sqlite3_close( dbhandle ), SQLITE_OK, "Failed to close db" ); 
}

해결법

  1. ==============================

    1.한 번에 800 개의 모든 요소를 ​​삽입하고 있습니까? 당신이 경우, 트랜잭션 내에서 삽입을하고 극적 과정을 빠르게합니다.

    한 번에 800 개의 모든 요소를 ​​삽입하고 있습니까? 당신이 경우, 트랜잭션 내에서 삽입을하고 극적 과정을 빠르게합니다.

    http://www.sqlite.org/faq.html#q19 참조

    SQLite는 매우 큰 데이터베이스를 처리 할 수 ​​있습니다. http://www.sqlite.org/limits.html 참조

  2. ==============================

    2.난 당신의 코드를 검토 한 결과, 나는 당신이 준비하고 마무리 문으로 무리 것 같아요. 나는 결코 SQLite는 전문가,하지만 루프를 통해 문장을 각각의 모든 시간을 준비에 상당한 오버 헤드가있을거야.

    난 당신의 코드를 검토 한 결과, 나는 당신이 준비하고 마무리 문으로 무리 것 같아요. 나는 결코 SQLite는 전문가,하지만 루프를 통해 문장을 각각의 모든 시간을 준비에 상당한 오버 헤드가있을거야.

    SQLite는 웹 사이트에서 인용 :

    http://www.sqlite.org/cintro.html

    귀하의 경우에는, 오히려 새로운 문 매번 준비하는 대신 기존 문에 새 값을 바인딩을 시도 할 수 있습니다.

    이 말한 모든, 난 당신이 더 많은 데이터를 추가로 시간이 계속 증가하기 때문에, 인덱스가 실제 범인있을 것 같아요. 나는 주말에 몇 가지 테스트를 할 계획 곳 나는 이것에 대해 충분히 궁금합니다.

  3. ==============================

    3.그냥 몇 가지 세부 사항을 놓을 곳으로 내 자신의 질문에 대답 :

    그냥 몇 가지 세부 사항을 놓을 곳으로 내 자신의 질문에 대답 :

    (정확하게 위의 제안)는 인덱스 작성이 느린 단계라고 밝혀, 나는 삽입의 또 다른 거래를 할 때마다, 인덱스는 약간의 시간이 소요되는 업데이트됩니다. 내 솔루션이다 : (A) 데이터 테이블을 작성 내 모든 기록 데이터 (몇 년 가치) 삽입 (B) (C) 인덱스를 작성

    이제 모든 조회 등 정말 빨리하고 SQLite는 훌륭한 일을한다. 이후 매일 업데이트는 이제 800 레코드를 삽입하는 데 몇 초가 걸릴 수 있지만, 그것은 단지 매 10 분 정도를 실행하기 때문에 그 문제가되지 않습니다.

    위의 도움말 / 제안 / 답변 로버트 하비에 감사 maxwellb.

  4. ==============================

    4.우리는 수도 실제로 일이 무엇인지 테이블에 인덱스가 없을 때 데이터를 캡처하는 빠른 것을 알고 있기 때문에 :

    우리는 수도 실제로 일이 무엇인지 테이블에 인덱스가 없을 때 데이터를 캡처하는 빠른 것을 알고 있기 때문에 :

    이 기술은 SELECT 문을 걸리는 INSERT INTO 빠른 개별 INSERT들을 실행하기보다는 이론에 근거한다.

    2 단계는 아직 조금 느린 것으로 판명되면, 비동기 모듈을 사용하여 백그라운드에서 실행 할 수 있습니다. 이것은 캡처 사이 중단 비트을 이용한다.

  5. ==============================

    5.인덱스없이, 주어진 일의 새로운 삽입을 위해 테이블을 사용하는 것이 좋습니다. 그런 다음 각 하루의 끝에서,하는 스크립트를 실행합니다 :

    인덱스없이, 주어진 일의 새로운 삽입을 위해 테이블을 사용하는 것이 좋습니다. 그런 다음 각 하루의 끝에서,하는 스크립트를 실행합니다 :

    당신은 O (n)은 오늘날의 데이터 O (로그 n) 및 조회 역사적 데이터에 대한 조회를 할 수 있다면, 이것은 좋은 타협을 제공해야한다.

  6. ==============================

    6.나는 당신의 사양에서 말할 수 있지만, ID 필드는 항상 증가되는 경우, 시간 필드는 고유성 YYYYMMDD을 포함하고 또한 항상 증가, 당신은 다음 간단한 비 데이터베이스 ID를 검색 또는 시간 검색 중 하나를 수행하고 솔루션은 (예를 들어,와 첫 번째 레코드를 찾아 원하는 레코드에 대한 이진 검색을 수행하는 (그들이에서 생성되는 것부터 순서 "분류") 및 코드를 사용 고정 필드 텍스트 또는 이진 파일로 간단하게 APPEND 모든 기록하는 것 또는 ID 관심있는 시간은, 순차적으로) 원하는 범위 단계별.

    나는 당신의 사양에서 말할 수 있지만, ID 필드는 항상 증가되는 경우, 시간 필드는 고유성 YYYYMMDD을 포함하고 또한 항상 증가, 당신은 다음 간단한 비 데이터베이스 ID를 검색 또는 시간 검색 중 하나를 수행하고 솔루션은 (예를 들어,와 첫 번째 레코드를 찾아 원하는 레코드에 대한 이진 검색을 수행하는 (그들이에서 생성되는 것부터 순서 "분류") 및 코드를 사용 고정 필드 텍스트 또는 이진 파일로 간단하게 APPEND 모든 기록하는 것 또는 ID 관심있는 시간은, 순차적으로) 원하는 범위 단계별.

  7. ==============================

    7.큰 SQLite는 데이터베이스를 구축 할 때 이전에 인덱스를 만들 수있는, 항상 데이터를 많이 삽입합니다. 즉 빠르게 데이터를 삽입하기 전에 인덱스를 만드는 것보다 여러 번 실행됩니다.

    큰 SQLite는 데이터베이스를 구축 할 때 이전에 인덱스를 만들 수있는, 항상 데이터를 많이 삽입합니다. 즉 빠르게 데이터를 삽입하기 전에 인덱스를 만드는 것보다 여러 번 실행됩니다.

  8. ==============================

    8.테이블의 행의 이론적 인 최대 수는 2 ^ 64 (18,446,744,073,709,551,616 또는 1.8E + 19에 대해)이다. 140 테라 바이트의 최대 데이터베이스 크기 먼저 도달 할 것이기 때문에이 한계에 도달 할 것이다. 140 테라 바이트의 데이터베이스는 각 행이 매우 적은 데이터를 포함하는 경우가 전혀없는 인덱스 만이라면 약 1E + 13 행보다 더 길게하지 않고, 수있다.

    테이블의 행의 이론적 인 최대 수는 2 ^ 64 (18,446,744,073,709,551,616 또는 1.8E + 19에 대해)이다. 140 테라 바이트의 최대 데이터베이스 크기 먼저 도달 할 것이기 때문에이 한계에 도달 할 것이다. 140 테라 바이트의 데이터베이스는 각 행이 매우 적은 데이터를 포함하는 경우가 전혀없는 인덱스 만이라면 약 1E + 13 행보다 더 길게하지 않고, 수있다.

  9. from https://stackoverflow.com/questions/3160987/can-sqlite-handle-90-million-records by cc-by-sa and MIT license