2009-12-14 6 views
1

약 1 백만 행의 테이블이 있습니다. 나는 각 행에서 하나의 필드를 출력하는 간단한 프로그램을 만들고있다. 그러나, mysql_pconnect와 mysql_query를 사용하기 시작하면 쿼리가 오랜 시간이 걸릴 것이고, 첫 번째 행까지도 출력 할 수 있으려면 쿼리가 완료되어야한다고 가정하고 있습니다. 한 번에 조금씩 데이터를 처리 할 수있는 방법이 있습니까? 나는 작은 데이터 집합을 검색 할 찾고 있지 않다PHP 한 번에 한 부분 씩 SQL 쿼리를 실행하는 방법?

--Edited-- , 나는 말 10 행, 인쇄 10 개 행을 페치 (데이터를 한 번에 덩어리를 처리하는 방법을 찾고 있어요 , 10 개의 행을 가져오고, 10 개의 행을 인쇄하는 등). 쿼리가 1 백만 행을 검색하고 (얼마나 오랫동안 알고 있는지) 기다린 다음 인쇄를 시작합니다.

+0

flush() (http://br2.php.net/flush) – Cesar

+0

한 번에 10 개의 행을 화면 10에 표시 했더라도 이는 브라우저로 전송할 데이터의 양이 엄청납니다. 디스플레이. 어떤 종류의 페이지 매김을 사용하지 않으면 대부분의 사용자 브라우저가 손상 될 가능성이 있습니다. – user103219

+0

글쎄, 그는 내가 아는 것을/dev/null에 인쇄 할 수 있습니다. –

답변

3

100 만 개의 필드 인쇄에는 다소 시간이 걸립니다. 1 백만 레코드를 검색하는 데는 약간의 시간이 걸립니다. 시간이 합산됩니다.

코드를 프로파일 한 적이 있습니까?한계를 사용하는 것이이 경우에 큰 차이를 만들지 모르겠다.

한 번에이

while ($row = mysql_fetch_object($res)) { 
    echo $row->field."\n"; 
} 

출력 하나 개의 기록처럼 뭔가를하고. 반환 된 전체 결과 집합을 기다리지 않습니다.

브라우저를 다루는 경우 더 많은 것이 필요합니다.

이러한이

ob_start(); 
$i = 0; 
while ($row = mysql_fetch_object($res)) { 
    echo $row->field."\n"; 
    if (($i++ % 1000) == 0) { 
     ob_flush(); 
    } 
} 
ob_end_flush(); 
+0

질문을 참조하십시오. – erotsppa

1

이것은 일반적으로 페이지 매김에 필요합니다. select 쿼리에서 limit 키워드를 사용할 수 있습니다. 한도 검색 here :

LIMIT 절을 사용하면 SELECT 문에서 반환하는 행 수를 제한 할 수 있습니다. LIMIT는 하나 또는 두 개의 숫자 인수를 취하는데, 둘 다 음수가 아닌 정수 상수 여야합니다 (준비된 명령문을 사용할 때 제외).

두 인수를 사용하면 첫 번째 인수는 반환 할 첫 번째 행의 오프셋을 지정하고 두 번째 인수는 반환 할 최대 행 수를 지정합니다. 초기 행의 오프셋은 0 (하지 1)입니다 :

SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15 

, 당신은 두 번째에 대한 몇 가지 큰 숫자를 사용할 수있는 일정에서 모든 행을 검색 결과 세트의 마지막까지 상쇄 매개 변수. 이 문은 마지막 96 번째 행에서 모든 행을 검색합니다

:

하나 개의 인수로
SELECT * FROM tbl LIMIT 95,18446744073709551615; 

이 값은 결과 집합의 시작부터 반환 할 행의 수를 지정합니다

SELECT * FROM tbl LIMIT 5;  # Retrieve first 5 rows 

즉, LIMIT row_count는 LIMIT 0, row_count와 같습니다.

+0

질문을 참조하십시오 – erotsppa

2

100 만 개의 필드를 실제로 인쇄 하시겠습니까?

일반적인 해결책은 웹 응용 프로그램에서 일종의 출력 페이지 매김을 사용하여 결과의 ​​일부만 표시하는 것입니다. SELECT 쿼리에서는 LIMIT 키워드를 사용하여 일부 데이터 만 반환 할 수 있습니다. 이것은 기본적인 SQL 기능입니다. 예 :

SELECT * FROM table WHERE (some conditions) LIMIT 40,20 

은 40 번째부터 시작하여 20 번째 항목을 표시합니다 (내 실수로 한 번씩 실수로 가능).

과 함께 ORDER BY을 사용해야 주문간에 요청에 따라 주문이 무작위로 변경되는 것을 방지 할 수 있습니다.

+0

질문을 참조하십시오 – erotsppa

0

과 같이 출력에 flushMysqli::use_result

결합 브라우저로 설정 데이터를 사용할 수 있습니다. mysqli :: use_result가 불완전한 결과 집합을 검색하는 올바른 함수인지 여부는 확실하지 않지만 플러시를 사용하여 점진적 상태에서 브라우저에 데이터를 출력하는 데 사용할 수 있습니다.

0

오라클과 같은 방식입니다. 어떻게 넘어갈 지 모르겠습니다.

declare 
my_counter integer := 0; 
begin 
for cur in (
select id from table 
) loop 
    begin 
    -- do whatever your trying to do 
    update table set name = 'steve' where id = cur.id; 
    my_counter := my_counter + 1; 
    if my_counter > 500 then 
     my_counter := 0; 
     commit; 
    end if; 
    end; 
    end loop; 
    commit; 
end; 
0

기본 mysql 드라이버를 사용한 예입니다.

define('CHUNK_SIZE', 500); 

$result = mysql_query('select count(*) as num from `table`'); 
$row = mysql_fetch_assoc($result); 

$totalRecords = (int)$row['num']; 

$offsets = ceil($totalRecords/CHUNK_SIZE); 

for ($i = 0; $i < $offsets; $i++) 
{ 
    $result = mysql_query("select * from `table` limit " . CHUNK_SIZE . " offset " . ($i * CHUNK_SIZE)); 
    while ($row = mysql_fetch_assoc($result)) 
    { 
    // your per-row operations here 
    } 
    unset($result, $row); 
} 

이렇게하면 메모리 사용량을 줄이기 위해 한 번에 500 행만 전체 행 볼륨을 반복합니다.

0

mysql 서버 내에서 다양한 버퍼 크기의 한계를 맞추고있는 것처럼 들리 네요. 당신이 할 수있는 방법 중 하나는 SQL 문에서 원하는 버퍼 크기를 줄이거 나 주위를 놀고 싶은 필드를 지정하는 것입니다 다양한 관리자 설정으로

OR, 당신이 방법 같은 매김 를 사용할 수 있지만 출력 모두 한 페이지가 ...

(의사)

function q($part) { 
     $off = $part*SIZE_OF_PARTITIONS; 
     $size = SIZE_OF_PARTITIONS; 

     return(execute_and_return_sql('SELECT `field` FROM `table` LIMIT $off, $size')); 
    } 

    $ii = 0; 

    while ($elements = q($ii)) { 
     print_fields($elements); 
     $ii++; 
    } 
0

사용 mysql_unbuffered_query() 또는 PDO가 PDO::MYSQL_ATTR_USE_BUFFERED_QUERY이 있는지 확인 사용하는 경우 false.

this similar question도 참조하십시오.

편집 : 다른 사람이 말했듯이, 상황에 따라 처리의 각 배치 후에 출력 버퍼를 플러시하는 것과 결합 할 수 있습니다.

관련 문제