2016-07-19 2 views
1

.csv 파일로 내보내는 데 필요한 매우 큰 데이터베이스 테이블 (700k 개 이상의 레코드)이 있습니다. 이를 내보내기 전에 GUI를 통해 사용자가 제공 한 몇 가지 옵션을 확인하고 레코드를 필터링해야합니다. 불행히도이 필터링 작업은 SQL 코드를 통해 수행 할 수 없습니다 (예 : 열에 일련 화 된 데이터가 포함되어 있으므로 레코드를 병합하여 필터링 규칙을 "통과"해야하는지 확인해야합니다.)PHP : MySQL 데이터베이스에서 많은 양의 데이터 필터링 및 내보내기

모든 레코드를 한꺼번에 수행하면 메모리가 생성됩니다 제한된 문제가 있으므로 50k 레코드 청크로 프로세스를 중단하기로 결정했습니다. 따라서 한 번에 700k 레코드를로드하는 대신 50k 레코드를로드하고 필터를 적용하고 .csv 파일에 저장 한 다음 다른 50k 레코드를로드하고 계속 진행할 것입니다. (700k 레코드에 도달 할 때까지).이 방법으로 메모리 문제는 피할 수 있지만 약 3 분 걸립니다 (레코드 수가 증가하면이 시간이 증가합니다).

다른 방법이 있습니까? 데이터베이스 구조를 변경하지 않고이 프로세스 (시간면에서 더 낫다)?

미리 감사드립니다.

+1

[key_buffers] (http://stackoverflow.com/questions/3663515/mysql-what-is-the-key-buffer)로 돌아 다니면서 읽을 수있는 동안 InnoDB에서 MyISAM으로 전환 한 다음 다시 전환 할 수 있습니다. 확실하게 다른 방법이 있습니다. 특히 mysql 설정을 사용하는 것이 좋습니다. – Andrew

+0

700K 행은 중간 크기입니다. * 현대 시스템에서 매우 큰 *은 100M 행 이상입니다. –

+0

죄송합니다 @OllieJones, 나는 그것에 대해 몰랐습니다 –

답변

0

달리 말하지 않는 한, PHP는 전체 결과 집합을 RAM에 한꺼번에 표시합니다. 버퍼링 된 쿼리는 입니다. 발견 한 결과 세트에 결과가 수백 개가 넘는 경우에는 작동하지 않습니다.

php의 설계자는 몇 줄의 데이터를 읽고 표시해야하는 웹 사이트 개발자가 버퍼링 된 쿼리를 사용하여 간단하게 만들 수있게되었습니다.

당신이하고있는 일을 수행하려면 unbuffered query가 필요합니다. PHP 프로그램은 한 번에 한 행을 읽고 처리합니다. 그러나 프로그램이 버퍼되지 않은 결과 집합의 모든 행을 읽도록주의하십시오. 부분 결과 집합을 MySQL과 PHP 프로그램 사이의 림보 매달기에 놓아두면 실제로 파울을 일으킬 수 있습니다.

mysqli 또는 PDO 중 어느 것을 사용하는지 말하지 않았습니다. 두 가지 모두 쿼리를 버퍼링하지 않도록 모드 설정을 제공합니다. 예전의 skool mysql_ 인터페이스를 사용한다면 아마 운이 좋지 않을 것입니다.

+0

감사합니다 @Ollie Jones. PDO를 사용하고 있습니다. 귀하의 제안은 메모리 사용량을 감소 시키지만 서버의로드를 증가시키지 않을 것입니까? –

+0

무슨 서버인지 모르겠습니다. MySQL 서버를 손상시키지 않습니다. 실제로 당신이 하나의 질의만을 실행하기 때문에 도움이 될 것입니다. 샤드를 생성하기 위해'ORDER BY ... LIMIT' 절을 사용할 필요가 없습니다. 귀하의 PHP 프로그램을 실행하는 웹 서버는 어느 정도의 작업을 수행하는 것과 거의 동일한 수준의 작업을 수행합니다. 특히 상업용 호스팅 서비스의 공유 서버에 3 분이 걸리는 것은 무리가 아닙니다. –

+0

버퍼링되지 않은 쿼리를 사용하는 경우 프로세스가 끝날 때까지 테이블이 잠겨 있거나 다른 프로세스에서 읽기/쓰기가 가능합니까? –

1

가능한 한 최선을 다해서 PHP를 가능한 한 많이 만들어내는 것입니다. 항상 CSV를로드하거나 내보내는 경우입니다.

아래에는 2600 만 행의 학생 테이블이 있습니다. 200K 행을 내보낼 것입니다. 허락하면, 칼럼 수는 학생 테이블에서 작습니다. 주로 학생들을위한 캠퍼스 정보로 수행하는 다른 것들을 테스트합니다. 그러나 당신은 내가 바라는 생각을 얻을 것이다. 문제는 귀하의 컴퓨터에 걸리는 시간입니다.

... 그런 다음 레코드가 필터링 규칙을 "통과"하는지 확인하십시오.

PHP가없는 이론에서는 db 엔진을 통해 자연적으로 발생할 수 있습니다. PHP가 없으면 진언이어야합니다. 그러나 아직 결정되지 않았습니다. 요점은, PHP 방정식 처리를 얻는 것입니다. PHP는 많은 것들이 있습니다. DB 처리에서 적절한 파트너가 아닙니다.

select count(*) from students; 
-- 26.2 million 

select * from students limit 1; 
+----+-------+-------+ 
| id | thing | camId | 
+----+-------+-------+ 
| 1 |  1 | 14 | 
+----+-------+-------+ 

drop table if exists xOnesToExport; 
create table xOnesToExport 
( id int not null 
); 
insert xOnesToExport (id) select id from students where id>1000000 limit 200000; 
-- 200K rows, 5.1 seconds 

alter table xOnesToExport ADD PRIMARY KEY(id); 
-- 4.2 seconds 

SELECT s.id,s.thing,s.camId INTO OUTFILE 'outStudents_20160720_0100.txt' 
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' 
    LINES TERMINATED BY '\r\n' 
    FROM students s 
    join xOnesToExport x 
    on x.id=s.id; 
-- 1.1 seconds 

위의 1AM 타임 스탬프 파일은 200K 행을 포함하여 결합을 통해 CSV로 내보내졌습니다. 1 초가 걸렸습니다.

LOAD DATA INFILESELECT INTO OUTFILE은 원 테이블 이동에 비해 속도가 떨어질 수는없는 한 가지 기능인 보조 기능입니다. 둘째, 사람들은 거의 후자를 사용하는 것처럼 보이지 않습니다.유스 케이스와 트릭을 통해 수행 할 수있는 모든 작업을 살펴 ​​본다면 유연합니다.

Linux의 경우 LINES TERMINATED BY '\n'을 사용하십시오. 위의 코드 블록이있는 Windows 컴퓨터를 사용하고 있습니다. 유일한 차이점은 파일 경로 및 줄 종결자가되는 경향이 있습니다.

관련 문제