[SQL] 9000 만 개 기록을 처리 SQLite는 할 수 있습니까?
SQL9000 만 개 기록을 처리 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.한 번에 800 개의 모든 요소를 삽입하고 있습니까? 당신이 경우, 트랜잭션 내에서 삽입을하고 극적 과정을 빠르게합니다.
한 번에 800 개의 모든 요소를 삽입하고 있습니까? 당신이 경우, 트랜잭션 내에서 삽입을하고 극적 과정을 빠르게합니다.
http://www.sqlite.org/faq.html#q19 참조
SQLite는 매우 큰 데이터베이스를 처리 할 수 있습니다. http://www.sqlite.org/limits.html 참조
-
==============================
2.난 당신의 코드를 검토 한 결과, 나는 당신이 준비하고 마무리 문으로 무리 것 같아요. 나는 결코 SQLite는 전문가,하지만 루프를 통해 문장을 각각의 모든 시간을 준비에 상당한 오버 헤드가있을거야.
난 당신의 코드를 검토 한 결과, 나는 당신이 준비하고 마무리 문으로 무리 것 같아요. 나는 결코 SQLite는 전문가,하지만 루프를 통해 문장을 각각의 모든 시간을 준비에 상당한 오버 헤드가있을거야.
SQLite는 웹 사이트에서 인용 :
http://www.sqlite.org/cintro.html
귀하의 경우에는, 오히려 새로운 문 매번 준비하는 대신 기존 문에 새 값을 바인딩을 시도 할 수 있습니다.
이 말한 모든, 난 당신이 더 많은 데이터를 추가로 시간이 계속 증가하기 때문에, 인덱스가 실제 범인있을 것 같아요. 나는 주말에 몇 가지 테스트를 할 계획 곳 나는 이것에 대해 충분히 궁금합니다.
-
==============================
3.그냥 몇 가지 세부 사항을 놓을 곳으로 내 자신의 질문에 대답 :
그냥 몇 가지 세부 사항을 놓을 곳으로 내 자신의 질문에 대답 :
(정확하게 위의 제안)는 인덱스 작성이 느린 단계라고 밝혀, 나는 삽입의 또 다른 거래를 할 때마다, 인덱스는 약간의 시간이 소요되는 업데이트됩니다. 내 솔루션이다 : (A) 데이터 테이블을 작성 내 모든 기록 데이터 (몇 년 가치) 삽입 (B) (C) 인덱스를 작성
이제 모든 조회 등 정말 빨리하고 SQLite는 훌륭한 일을한다. 이후 매일 업데이트는 이제 800 레코드를 삽입하는 데 몇 초가 걸릴 수 있지만, 그것은 단지 매 10 분 정도를 실행하기 때문에 그 문제가되지 않습니다.
위의 도움말 / 제안 / 답변 로버트 하비에 감사 maxwellb.
-
==============================
4.우리는 수도 실제로 일이 무엇인지 테이블에 인덱스가 없을 때 데이터를 캡처하는 빠른 것을 알고 있기 때문에 :
우리는 수도 실제로 일이 무엇인지 테이블에 인덱스가 없을 때 데이터를 캡처하는 빠른 것을 알고 있기 때문에 :
이 기술은 SELECT 문을 걸리는 INSERT INTO 빠른 개별 INSERT들을 실행하기보다는 이론에 근거한다.
2 단계는 아직 조금 느린 것으로 판명되면, 비동기 모듈을 사용하여 백그라운드에서 실행 할 수 있습니다. 이것은 캡처 사이 중단 비트을 이용한다.
-
==============================
5.인덱스없이, 주어진 일의 새로운 삽입을 위해 테이블을 사용하는 것이 좋습니다. 그런 다음 각 하루의 끝에서,하는 스크립트를 실행합니다 :
인덱스없이, 주어진 일의 새로운 삽입을 위해 테이블을 사용하는 것이 좋습니다. 그런 다음 각 하루의 끝에서,하는 스크립트를 실행합니다 :
당신은 O (n)은 오늘날의 데이터 O (로그 n) 및 조회 역사적 데이터에 대한 조회를 할 수 있다면, 이것은 좋은 타협을 제공해야한다.
-
==============================
6.나는 당신의 사양에서 말할 수 있지만, ID 필드는 항상 증가되는 경우, 시간 필드는 고유성 YYYYMMDD을 포함하고 또한 항상 증가, 당신은 다음 간단한 비 데이터베이스 ID를 검색 또는 시간 검색 중 하나를 수행하고 솔루션은 (예를 들어,와 첫 번째 레코드를 찾아 원하는 레코드에 대한 이진 검색을 수행하는 (그들이에서 생성되는 것부터 순서 "분류") 및 코드를 사용 고정 필드 텍스트 또는 이진 파일로 간단하게 APPEND 모든 기록하는 것 또는 ID 관심있는 시간은, 순차적으로) 원하는 범위 단계별.
나는 당신의 사양에서 말할 수 있지만, ID 필드는 항상 증가되는 경우, 시간 필드는 고유성 YYYYMMDD을 포함하고 또한 항상 증가, 당신은 다음 간단한 비 데이터베이스 ID를 검색 또는 시간 검색 중 하나를 수행하고 솔루션은 (예를 들어,와 첫 번째 레코드를 찾아 원하는 레코드에 대한 이진 검색을 수행하는 (그들이에서 생성되는 것부터 순서 "분류") 및 코드를 사용 고정 필드 텍스트 또는 이진 파일로 간단하게 APPEND 모든 기록하는 것 또는 ID 관심있는 시간은, 순차적으로) 원하는 범위 단계별.
-
==============================
7.큰 SQLite는 데이터베이스를 구축 할 때 이전에 인덱스를 만들 수있는, 항상 데이터를 많이 삽입합니다. 즉 빠르게 데이터를 삽입하기 전에 인덱스를 만드는 것보다 여러 번 실행됩니다.
큰 SQLite는 데이터베이스를 구축 할 때 이전에 인덱스를 만들 수있는, 항상 데이터를 많이 삽입합니다. 즉 빠르게 데이터를 삽입하기 전에 인덱스를 만드는 것보다 여러 번 실행됩니다.
-
==============================
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 행보다 더 길게하지 않고, 수있다.
from https://stackoverflow.com/questions/3160987/can-sqlite-handle-90-million-records by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 당신은 어떻게 대소 문자를 구별 할 MySQL의 LIKE를 강요하는 걸까? [복제] (0) | 2020.06.22 |
---|---|
[SQL] 당신은 세미콜론을 사용해야 할 때 SQL Server에서 때 GO를 사용한다? (0) | 2020.06.22 |
[SQL] 비트 중 하나가 일치하는 경우 SQL에 두 개의 비트 마스크를 비교하는 것은 볼 수 (0) | 2020.06.22 |
[SQL] 각 루프에 대한 SQL 서버 (0) | 2020.06.22 |
[SQL] (다른 테이블이다)의 다른 컬럼에 하나 개의 컬럼 데이터를 복사 (0) | 2020.06.22 |