2016-06-27 2 views
4

Итак, у меня есть эта база данных с 435 453 строками данных. И у меня есть 271 компания, которая нуждается в конкретной информации, поэтому в настоящее время я пытаюсь ее агрегировать, выбирая все данные с помощью MySQL-запроса, который возвращает все строки в 1.28 секунд.Запись в файлы медленная

Затем я хочу пройти их и записать их в файлы (используя fputcsv()) согласно каждой компании. Поэтому я начинаю с использования fopen() 271 раз для создания файлов, а затем для каждой возвращенной строки я вижу, какие компании будут иметь данные в этой строке и соответственно записать в файлы.

Теперь, используя memory_usage(), я вижу, что использование памяти на устойчивом 6Mb в течение всего процесса. И используя microtime(), я выбираю каждую итерацию while(), которую я читаю из БД.

И конечный результат состоит в том, что каждая итерация занимает около 0,00001 секунды, поэтому для каждой строки в БД требуется 0,00001 секунд, чтобы определить, какие компании должны иметь каждую строку и записывать ее в эти файлы.

Но что-то перепуталось, потому что через 100 минут процесс все еще не выполнен, а while() продвигается примерно на 100 строк каждую секунду. И если моя математика правильная, пройдя 435 453 строки, каждая из которых занимает 0,00001 секунд, занимает около 4 секунд.

Вот код, или часть, которая так долго:

$q=mysql_query(bq($query)) or print mysql_error(); 
while ($r=mysql_fetch_assoc($q)){ 
    $nr++; 
    $now = microtime(true); 
    if (($nr % 100) == 0 && $argv[1] == "debug"){ 
     print "$nr: " . fsize(memory_get_usage()) . ", time: " . sprintf("%.5f", ($now - $savetime)) . "\n"; 
    } 
    foreach ($xsps as $xsp => $sites){ 
     if (!in_array($r["citynet"], $sites)) continue 1; 
     $data = format_fields($r, $xsp); 
     $values = array_values($data); 
     $keys = array_keys($data); 
     $linefeed = "\n"; 
     # TXT 
     if ($nr == 1) fwrite($text[$xsp], join("\t", $keys) . $linefeed); 
     fputcsv($text[$xsp], $values, "\t"); 
     # CSV 
     if ($nr == 1) fwrite($csv[$xsp], join(";", $keys) . $linefeed); 
     fputcsv($csv[$xsp], $values, ";"); 
    } 
    $savetime = microtime(true); 
} 

И выход, который печатает каждые 100 строк, выглядит примерно так:

12600: 6 Mb, time: 0.00000 
12700: 6 Mb, time: 0.00000 
12800: 6 Mb, time: 0.00000 
12900: 6 Mb, time: 0.00001 
13000: 6 Mb, time: 0.00000 
13100: 6 Mb, time: 0.00000 
13200: 6 Mb, time: 0.00000 

Таким образом, очевидно, - Что я делаю не так? Как это может занять столько времени, когда цифры говорят, что нет?

EDIT Таким образом, очевидно, что я имел, как я вычисленный это неправильно, поэтому я редактировал это:

while ($r=mysql_fetch_assoc($q)){ 
    $nr++; 
    $start = microtime(true); 
    if (($nr % 100) == 0 && $argv[1] == "debug"){ 
     print "$nr: " . fsize(memory_get_usage()) . ", time: " . sprintf("%.5f", $processtime) . "\n"; 
    } 
    ... 
    $stop = microtime(true); 
    $processtime = ($stop - $start); 
} 

И теперь он сообщает, что каждая строка занимает 0,15 секунды для завершения, что означает, что весь процесс занимает 108 минут. Итак, теперь возникает вопрос: почему он так медленно? Является ли fputcsv() медленным или это медленный PHP?

+0

Время выглядит неправильно. После цикла foreach вы сохраняете время, а затем возвращаетесь к началу цикла while и снова получаете время. '$ now' вычисляется почти сразу после' $ savetime'. Я думаю, вы должны вычислять '$ savetime', когда' $ nr% 100 == 0' и '$ savetime' должны идти в начале, а время' $ now' должно идти после foreach и вычислять разницу тогда , – drew010

+0

@Ctc Нет, это запускается из командной строки – Sandman

+0

@sandman. Мой плохой, действительно не прочитал его правильно. Позвольте мне еще раз прочитать. – Ctc

ответ

-1

У меня нет возможности отлаживать код и базу данных.

Но я хотел бы начать с изменения этого осуждается mysql_* код:

$q=mysql_query(bq($query)) or print mysql_error(); 
while ($r=mysql_fetch_assoc($q)){ 

этой версии PDO, как:

$dsn = 'mysql:dbname=testdb;host=127.0.0.1'; 
$user = 'dbuser'; 
$password = 'dbpass'; 

try { 
    $dbh = new PDO($dsn, $user, $password); 
} catch (PDOException $e) { 
    echo 'Connection failed: ' . $e->getMessage(); 
} 

$sth = $dbh->prepare($q); 
$sth->execute(); 

$result = $sth->fetchAll(PDO::FETCH_ASSOC); // <-- this is important to get all records from mysql but not one by one 
foreach($result as $r) { 
+0

Я делаю именно это, но это совсем другое дело, соединение с MySQL и запрос не то, что здесь занимает время. – Sandman

+0

На самом деле получение элементов один за другим, с немедленной обработкой и забыванием массивов результатов, большей эффективностью памяти. – Arnial

+0

Накачка 435,453 записей в память кажется плохой идеей. Возможно, измените свой пример на использование простого 'while ($ row = $ sth-> fetch (PDO :: FETCH_ASSOC)) {...}' – Pieter

Смежные вопросы