2009-02-06 5 views
4

MS Access 테이블에 800000 개의 레코드를 삽입해야합니다. Delphi 2007 및 TAdoXxxx 구성 요소를 사용하고 있습니다. 이 테이블에는 정수 필드 하나, 한 개의 float 필드 및 하나의 문자가있는 텍스트 필드가 있습니다. 정수 필드 (autoinc가 아님) 중 하나에 기본 키가 있고 다른 정수와 float 필드에 두 개의 인덱스가 있습니다.800000 레코드를 MS Access 테이블에 삽입하려면 어떻게합니까?

AdoTable.AppendRecord(...)을 사용하여 데이터를 삽입하는 것은 사용자가 프로그램에서 새 데이터베이스를 사용하기 시작할 때마다 수행되므로 10 분을 초과합니다. 데이터가 ADO을 통해 액세스 할 수없는 다른 데이터베이스에서 제공되기 때문에 테이블을 미리 채울 수 없습니다.

는 내가 탭으로 구분 된 텍스트 파일에 기록을 작성하고

insert into table (...) select * from [filename.txt] in "c:\somedir" "Text;HDR=Yes" 

을 실행하기 tAdoCommand 개체를 사용하여 약 1 분으로 내려 관리하지만이의 오버 헤드를 좋아하지 않는다.

더 좋은 방법이 있어야한다고 생각합니다.

편집 :

몇 가지 추가 정보

: 그것은 대상 컴퓨터 (들) 및 전체 데이터베이스에 추가 설치가 필요하지 않기 때문에

  • MS 액세스가 선정되었다 하나 개의 파일에 포함되어 있습니다 쉽게 복사 할 수 있습니다.
  • 이것은 단일 사용자 응용 프로그램입니다.
  • 데이터는 한 번만 삽입되며 데이터베이스의 수명 동안 변경되지 않습니다. 그러나 테이블에는 다른 데이터베이스의 해당 레코드가 사용자에 의해 처리되었음을 나타내는 플래그로 사용되는 하나의 추가 필드가 들어 있습니다.
  • 1 분 입니다. 최대 3 분이 걸릴 수도 있고 내 솔루션이 작동하지만 너무 복잡해 보였으므로보다 쉬운 방법이 있어야한다고 생각했습니다.
  • 일단 데이터가 삽입되면 테이블의 성능이 상당히 좋아집니다.
  • Access 데이터베이스로 작업하는 프로그램의 기능을 계획/구현하기 시작했을 때 테이블이 필요하지 않았습니다. 나중에 고객이 다른 기능을 요청했을 때만 나중에 필요할 때가되었습니다. (즉, 항상 그런 것은 아닌가?)

편집 : 내가 지금까지 가지고 모든 해답에서

, 내가 이미 삽입하는 가장 빠른 방법을 가지고 있음을 보인다 Access 테이블에있는 데이터의 양. 모두에게 감사 드리며, 귀하의 도움에 감사드립니다.

+0

얼마나 빨리 필요합니까? 10 분이 소요되었다고 생각하면 가능한 한 빨리 처리 한 것처럼 보입니다. 이제는 1 분만 걸립니다. – Eppz

+0

1 분은 800000 개의 레코드를 삽입하는 데 매우 적합합니다. –

+0

1 분은 상당히 받아 들일 만하지만이 텍스트 파일을 만들지 않고 떠나고 싶습니다. – dummzeuch

답변

3

텍스트 기반 솔루션이 가장 빠른 것처럼 보일 수 있지만, 미리 할당 된 MS Access를 마지막에 가까운 크기로 가져올 수 있다면 더 빨리 얻을 수 있습니다. 일반적인 사용자 데이터베이스를 작성하고 응용 프로그램을 닫고 (버퍼가 플러시되도록) 큰 테이블의 모든 레코드를 수동으로 삭제할 수 있습니다. 그러나 축소/압축하지는 마십시오.

그래서 실제 채우기를 시작하기 위해 파일을 사용하십시오. 액세스는 추가 디스크 공간을 요청하지 않습니다. MS Access가 이것을 자동화하는 방법이 있다면 기억하지 못하지만 많은 도움이 될 수 있습니다 ...

+0

흥미로운 아이디어. 불행히도 그 테이블이 실제로 얼마나 커질 지 모르기 때문에 나에게 도움이되지 않을 것입니다. (800000 레코드는 제가 사용했던 테스트 케이스 였고 실제 크기는 액세스 테이블이 존재할 때 사용할 수없는 다른 테이블의 내용에 달려 있습니다. 만든다.) 아마 나는 그것을 채울 지 아닌지를보기 위해 몇 가지 테스트를 할 것이다. 500000 개의 레코드를 사용하면 이후 가져 오기 속도가 빨라지기에 충분합니다. – dummzeuch

+0

내 경험은 SQLServer에 대한 것이지만 다른 db 엔진 (예 : Firebird)은 똑같은 이유 때문에 dbfiles를 자동 축소하지 않습니다 : 가능한 경우 기본 OS에 새 디스크 공간 할당을 묻지 마십시오. SQLServer의 복원 작업조차 디스크 공간을 미리 할당합니다. –

+0

얼마나 개선 되었습니까? –

5

색인이 없으면 더 빠를 것입니다. 가져 오기 후에 추가 할 수 있습니까?

당신은 한 방향으로 올바른 방향으로 찾고있는이 스레드 Slow MSAccess disk writing

+0

예, 이것에 대해 생각했지만 일부 실험에서는 성능이 많이 향상되지 않았습니다. – dummzeuch

+0

그 링크는 재미있었습니다, 감사합니다. – dummzeuch

1

에 관심을 가질 수있는 제안이 될 것입니다. 단일 문을 사용하여 대량 삽입하는 것은 데이터를 반복하고 행별로 삽입하는 것보다 빠릅니다. 액세스, 파일 기반 데이터베이스가되는 것은 반복 쓰기 작업이 매우 느립니다.

문제는 Access가 내부적으로 쓰기를 최적화하는 방법을 처리하고 실제로 그것을 제어 할 방법이 없다는 것입니다. INSERT 문의 최대 효율에 도달했을 가능성이 높습니다. 추가 속도를 위해서는 응용 프로그램을 시작할 때마다 데이터베이스에 800,000 개의 레코드를 쓰는 방법이 있는지 평가해야합니다.

+0

OP는 사용자가 새 데이터베이스를 만들 때만 발생하며 앱이 시작될 때마다 발생하지는 않는다고 전했다. 그건 문제가 될 것입니다 :) –

+0

내가 응용 프로그램을 시작할 때마다되지 않습니다. 그것은 다른 도구를 사용하여 만든 새로운 액세스 데이터베이스를 사용하기 시작할 때만 발생합니다. 일단 데이터가 추가되면 데이터베이스의 수명 동안 변경되지 않습니다. – dummzeuch

1

SQL Server Express (무료)을 가져 와서 외부 테이블에 액세스하십시오. SQL Express는 MS Access보다 훨씬 빠릅니다.

+0

이 경우 옵션이 아닙니다. – dummzeuch

+1

SQL Server가 내장되어 있습니다. 설치가 필요없고 DLL 만 필요합니다. STIL La LOT가 Access보다 낫습니다. – TomTom

9

800K 레코드 데이터가 데이터베이스 수명 동안 변경되지 않는다고 했으므로 텍스트 파일에 테이블로 연결하고 삽입을 건너 뛰는 것이 좋습니다.

데이터베이스에 끌어 넣으 려한다면 1 분에 800,000 개의 레코드가 13,000/초 이상입니다. 나는 당신이 MS Access에서 그걸 이길 거라고 생각하지 않아.

사용자가보다 반응하도록하려면 최소한의 데이터 세트를로드하고 작동하는 동안 나머지를로드하도록 백그라운드 스레드를 설정하는 것이 좋습니다.

+1

사용자가 한 컴퓨터에서 다른 컴퓨터로 복사하여 작업을 계속할 수 있기 때문에 데이터베이스 내부의 데이터가 필요합니다. 연결을하면 텍스트 파일도 복사하고 경로를 유지해야합니다. 의도 된 사용자는이를 위해 컴퓨터로 충분하지 않습니다. – dummzeuch

+0

텍스트 파일을 테이블로 간단히 가져 오는 데 시간이 얼마나 걸리나요? (예 : 아무 곳에 나 삽입하지 않고 바로 가져 오기만 하시겠습니까?) – JosephStyons

0

아마도 잠금 모드 adLockBatchOptimistic 및 CursorLocation adUseClient이있는 테이블에 ADO 레코드를 열어 모든 데이터를 레코드 세트에 기록한 다음 일괄 업데이트 (rs.UpdateBatch)를 수행 할 수 있습니다.

3

어떻게 다른 배열에 대한 ...

는 당신이 필요로하고 그냥이 일 외에이 다른 모든 데이터를 삭제이 테이블에있는 기존 Access 데이터베이스 파일의 복사본을 만들 수있는 옵션이 될 것인가 큰 테이블 (Access가 SQL 서버에서 "truncate table"과 같은 것을 가지고 있는지 모른다)?

+0

그렇지 않으면 적어도 "테이블에서 삭제 *"가 작동해야합니다 –

0

또한 파일을 복사하는 데 걸리는 시간을 확인하십시오. 데이터를 작성할 수있는 속도의 하한이됩니다. db와 같은 SQL에서 일반적으로 대량로드 유틸리티를 사용하여 해당 속도에 가깝습니다. 지금까지 내가 아는 한, MS는 bcp와 같은 방법으로 MS Access 테이블에 직접 쓸 수있는 도구를 만들지 않았습니다. 특수화 된 ETL 도구는 SSIS가 메모리에서 변환하는 방식과 같이 삽입물을 둘러싼 일부 단계를 최적화합니다. DTS는 마찬가지로 일부 최적화 기능을 제공합니다.

1

데이터베이스를 미리 채우고 기존 (그러나 비어있는) 데이터베이스를 채우지 않고 파일 자체를 전달합니다.

기입해야하는 데이터가 변경되면 기본 데이터베이스에서 변경 사항을 확인하고 액세스 데이터베이스에 복사하는 코드를 사용하여 서버에서 ODBC 액세스 데이터베이스 (MDB 파일)를 동기화 된 상태로 유지하십시오.

사용자가 새 데이터베이스를 요청하여 MDB를 압축 한 다음 MDB를 열어서 엽니 다.

또는 데이터베이스를 열고 데이터를 직접 삽입하는 코드를 찾을 수 있습니다.

번갈아 가며 액세스가 더 빠른 다른 형식 (csv 제외)을 찾을 수 있습니다. 그것은 디베이스에서오고 경우

-Adam

+0

흠, 당신의 마지막 문장 생각 날 잡았어 : 현재 다른 데이터베이스는 dbase이고 실제로 ADO는 dbase를 읽을 수 있기 때문에 실제로 insert 문에서 원래 테이블을 사용할 수 있습니다 ... – dummzeuch

+0

그것은 나에게 더 많은 소리가 나고 원래 데이터가 전혀 바뀌지 않는 것처럼 보입니다. 그렇다면 최선의 선택은 데이터를 액세스 DB 파일에 한 번 작성한 다음 사용자가 "새"데이터베이스를 필요로 할 때 파일을 복사하는 것입니다. – pfunk

+0

아니요, 옵션이 아닙니다. 액세스 db는 사용자 정의 구성에 따라 작성됩니다. 항상 그 데이터베이스에있는 유일한 것은 문제의 테이블입니다. 또한 여러 주요 데이터베이스가 있으며 사용자가 액세스 db를 사용하기 시작할 때 활성 데이터베이스에서 복사해야합니다. – dummzeuch

0

, 당신은 단지 데이터와 인덱스 파일을 복사 및로드하지 않고 직접 첨부 할 수 있습니다? FoxPro를 가져 오는 사람들로부터 꽤 효율적이어야합니다. 기존 인덱스도 사용할 것이라고 상상합니다.

적어도이 명령은 매우 효율적인 단일 명령 가져 오기 여야합니다.

+0

아니, 할 수 없다. 새 테이블에는 실제로 이후 작업 중에 채우고 쿼리하는 추가 열이 하나 있습니다. – dummzeuch

4

텍스트 파일을 건너 뛰고 ODBC 또는 OLEDB를 사용하여 소스 테이블에서 직접 가져 오는 경우는 어떻게됩니까? 이는 소스 테이블 이름과 적절한 연결 문자열을 FROM 절의 IN 부분으로 사용하도록 FROM 절을 변경하는 것을 의미합니다.

EDIT : 사실 저는 원래 형식이 xBase라고 말합니다. 따라서 ODBC 나 OLEDB가 필요하지 않고 Jet의 일부인 xBase ISAM을 사용할 수 있어야합니다.

INSERT INTO table (...) 
SELECT * 
FROM tablename IN 'c:\somedir\'[dBase 5.0;HDR=NO;IMEX=2;]; 

당신은 그것을 조정할해야 할 수도 있습니다 - 난 그냥 DBF 파일을 가리키는 연결된 테이블에 대한 연결 문자열을 잡고, 그래서 매개 변수는 다소 차이가있을 수 있습니다 : 그것은 다음과 같이 보일 것입니다.

+0

이것은 가능할 수도 있지만, 모듈에 대한 다소 재 설계가 필요합니다 (현재 소스 테이블에 대해서는 모르지만 데이터를 가져 오기위한 인터페이스 만 있습니다). 내일 다시 확인해 볼게. – dummzeuch

+0

필자는 코드가 왜 문제가되는지 알지 못합니다. 텍스트 파일에서 INSERT를 실행 했으므로 텍스트 파일을 만드는 것을 건너 뛰고이 파일을에서 직접 INSERT로 바꾸는 것 같습니다. 런타임까지 tablename을 모르는 경우 SQL을 사용하여 작성된 테이블. –

0

한 창조물에서 다음 창조물까지 800,000 개의 레코드가 얼마나 바뀌나요? 레코드를 미리 채우고 새 데이터베이스를 만들 때 외부 데이터베이스에서 변경된 레코드 만 업데이트 할 수 있습니까?

이렇게하면 새 데이터베이스 파일을 더 빨리 만들 수 있습니다.

+0

사용자가 다른 마스터 데이터베이스로 전환 할 가능성이 있기 때문에 모든 레코드가 변경 될 수 있습니다. – dummzeuch

3

나는 MS Access를 다른 데이터베이스로 대체 할 것이고, 상황에 따라 Sqlite이 최선의 선택이며 클라이언트 컴퓨터에 설치가 필요하지 않으며 매우 빠른 데이터베이스와 최상의 내장 데이터베이스 솔루션 중 하나입니다.

  1. 당신은 Sqlite 웹 사이트에서 데이터베이스 엔진의 DLL을 다운로드하고 Delphi SQLite components 또는 SQLite4Delphi

  2. 사용 DISQLite3처럼 액세스 할 수 무료 델파이 구성 요소를 사용할 수 있습니다 : 당신은 두 가지 방법으로 델파이에서 사용할 수 있습니다

    엔진이 내장되어 있으며 응용 프로그램과 함께 dll을 배포 할 필요가 없습니다. 무료 버전이 있습니다.

여전히 MS Access를 사용해야하는 경우 TADOTable을 사용하는 대신 직접 SQL 삽입 명령으로 TAdoCommand를 사용하십시오. TADOTable.Append를 사용하는 것보다 빠릅니다.

+0

불행히도 현재 프로젝트에서 Access를 대체하는 것은 옵션이 아닙니다. – dummzeuch

+0

게다가, 레코드를 더 빨리 가져올 수 있습니까? –

0

디스크 회전 속도는 얼마나됩니까? 7200RPM이라면 3 분 안에 800,000 개의 행이 여전히 디스크 혁명 당 37 행입니다. 나는 네가 그보다 훨씬 잘할 것이라고 생각하지 않는다.

한편 목표가 프로세스를 간소화하는 것이라면 테이블 링크는 어떻습니까?

ADO를 통해 원본 데이터베이스에 액세스 할 수 없다고 가정 해보십시오. MS Access에서 소스 데이터베이스의 테이블 또는 뷰에 대한 테이블 링크를 설정할 수 있습니까? 그런 다음 테이블 링크의 간단한 추가 쿼리를 통해 원본 데이터베이스에서 대상 데이터베이스로 데이터를 복사합니다. 나는 잘 모르겠다. 그러나 나는 이것이 꽤 빠를 것이라고 생각한다.

런타임까지 테이블 링크를 설정할 수 없으면 ADO를 통해 프로그래밍 방식으로 테이블 링크를 작성한 다음 추가 쿼리를 프로그래밍 방식으로 작성한 다음 추가 쿼리를 호출 할 수 있습니다. 그들은 당신이 당신의 레코드의 txt 파일에 다음 대량 시간 3 초 미만이어야한다 테이블 에 txt 파일을 삽입 삽입해야 을 말했듯이

+0

액세스 데이터베이스와 마스터 데이터베이스는 모두 사용자 작업으로 인해 변경 될 수 있으므로 액세스 데이터베이스 내에 링크를 만드는 유일한 방법은 런타임에 수행됩니다. 나는 충분히 빠르고 구현하기 쉽고 ADO를 통해 링크를 생성하는 방법을 모르기 때문에 텍스트 파일 솔루션을 고수 할 것입니다. – dummzeuch

-3

HI 가장 좋은 방법은 TXT 파일에서 대량 삽입을합니다.

2

언급 된 사람과 같이 1 분 안에 80 만 건의 레코드를 가져올 수 없습니다. 그게 이고 실제로는입니다.

삽입을 수행하는 데 올바른 방법 (DAO 레코드 세트)을 사용하는 경우 귀찮은 번역 - 텍스트 파일 단계를 건너 뛸 수 있습니다. 이전 질문을 참조하십시오 StackOverflow에 대한 질문 : 대답 MS Access: Why is ADODB.Recordset.BatchUpdate so much slower than Application.ImportXML?

DAO에서도 INSERT INTO를 사용하지 마십시오. 천천히. ADO를 사용하지 마십시오. 천천히. 하지만 DAO + Delphi + Recordsets +는 DbEngine COM 개체를 직접 (Access.Application 개체 대신) 인스턴스화하여 속도를 크게 향상시킵니다.

+0

흥미로운 접근 방법. 나중에 시도해 보겠습니다 (문제의 프로그램은 이미 텍스트 파일 가져 오기 방법과 함께 제공되었습니다). – dummzeuch

관련 문제