Оптимизация парсинга очень большой выборки из БД

Poltoraki

Новичок
Оптимизация парсинга очень большой выборки из БД

Если я правильно понимаю, то после того как я вытскиваю данные из БД с помощью mysql_query, их можно представить в следующем виде матрицы. Ее максимальный размер у меня может быть 63 столбца Х 330000 строк. Ну что-то типа такого:
1 -> a(0), b(1), c(2) и до ...(63)
2 -> a(0), b(1), c(2) .....
........
330000-> a(0), b(1), c(2)....
На основе этой выборки надо сформировать текстовый файл очень специального формата. В структуре этого файла снужно сначала вывести некую служебную информацию, потом все значения a, потом b, ну и т.д. Больше всего времени занимает следующий кусок кода по парсингу результата выборки для вывода значений:
PHP:
for ($i = 0; $i < $count_arrOPColumns; $i++)// кол-во столбцов
{
     fwrite($fp, "{$_SESSION['arrOPColumns'][$i]} = ");//имя столбца
     mysql_data_seek($result, 0);// чтобы вернуть курсор в начало когда выберy все значения из этого столбца
    $j = 0;
    while ($row = mysql_fetch_row($result))
    {
          fwrite ($fp, $row[$i]);
          $j = $j + 1; //счетчик, чтобы поймать конец строки 
          if ($j == $_SESSION['$totalrows'])//$_SESSION['$totalrows'] - кол-во строк
          { 
               fwrite ($fp, ";\n\t");
          }
          else
          {
               fwrite ($fp, ", ");
          }
    } 
}
В этом куске в свою очередь очень много времени занимает возврат курсора в начало, я просто комментил эту строку и сравнивал, а как без этого обойтись - не знаю. Может быть и сам цикл вывода далеко не оптимален и кривоват. Гляньте пожалуйста свежим взглядом.
Спасибо!
 

[Gisma]

Новичок
я думаю лучше правильно организовать данные при выборке, либо в бд;)
 

Poltoraki

Новичок
[Gisma]
в самой выборке нет ничего лишнего, а время за которое вытаскиваются данные из БД несравнимо меньше с тем, за которое выполняется вышеприведенный кусок.
 

bkonst

.. хочется странного?...
... Или выводить в несколько временных файлов параллельно, а потом их склеить ...
 

Poltoraki

Новичок
bkonst
никогда такого не делал. Можно поподробнее про параллельный вывод?
 

bkonst

.. хочется странного?...
Я имею в виду открыть несколько файлов одновременно. В первый писать поля (a), во второй - (b) и так далее. Потом собрать в нужном порядке.
 

Poltoraki

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

bkonst

.. хочется странного?...
В этом куске в свою очередь очень много времени занимает возврат курсора в начало, я просто комментил эту строку и сравнивал, а как без этого обойтись - не знаю.
В предлагаемом способе выборка проходится только один раз.
 

CCCP_MOCKBA

Новичок
сначала выбрать все записи из БД в массив, а затем записывать файл. это ускорит процесс.
 

Poltoraki

Новичок
bkonst
понял, спасибо за идею!

CCCP_MOCKBA
это, наверное, скорее ускорит процесс записи, но можно попробовать. Тоже спасибо за идею!
 

_RVK_

Новичок
Poltoraki
Тебе нужно повернуть матрицу (уж не поиню как это по научному). Потом просто пройтись по массиву сверху вниз за один проход записать все в файл.
Итак задача оптимизации разделена на 2 части.
1. Алгоритм поворота матрицы.
2. Запись в файл.

Раздели эти алгоритмы в своей задаче, и выясни, на что тратится основное время. После этого можно будет начинать оптимизацию.
 

uninside

Новичок
а чего это вы делаете для каждой строки запись в файл????! пользуйтесь fwrite как можно реже, вы что?! это оччень долгая функция. оптимизируйте лучше чтобы записывал раз на 10000 строк, увидите разницу сразу!
 

zarus

Хитрожопый макак
Автор оригинала: uninside
а чего это вы делаете для каждой строки запись в файл????! пользуйтесь fwrite как можно реже, вы что?! это оччень долгая функция. оптимизируйте лучше чтобы записывал раз на 10000 строк, увидите разницу сразу!
10.000 строк - это очень много памяти. А если таких скриптов тыща штук? Начнется свап. Уж лучше сразу записать и "забыть".
 

_RVK_

Новичок
zarus, ты что телепат? Откуда ты знаешь сколько у него байт в каждой строке, сколько памяти, сколько копий скриптов запускается, как часто? Не сбивай человека с толку. Пусть сам выбирает баланс скорость/память. Ему виднее.
 

zarus

Хитрожопый макак
Автор оригинала: _RVK_
zarus, ты что телепат? Откуда ты знаешь сколько у него байт в каждой строке, сколько памяти, сколько копий скриптов запускается, как часто? Не сбивай человека с толку. Пусть сам выбирает баланс скорость/память. Ему виднее.
Ну собственно, я к тому и подводил, что нужно выбирать исходя из задачи, а не указывать вариант, как единственно "правильный" :)
 

Poltoraki

Новичок
После переборки всяческих вариантов самым быстрым является вот такой:
PHP:
while ($row = mysql_fetch_row($result))
{
	for ($i=0; $i < $count_arrOPColumns; $i++)
	{
		$TransposedData[$i][]= $row[$i];
	}
}
т.е. считываем по строкам, пишем в массив по столбцам, а потом считывая полученный массив по строкам пишем в файл. Все остальные способы медленнее раз в 5-7. Но тут возникает другая проблема: большие массивы в памяти занимают дико много места (как оказалось не я один с этом столкнулся, можно посмотреть тут: http://bugs.php.net/bug.php?id=13598). Получается, что если в $TransposedData содержатся все значения (330000) только одного из 63 возможных параметров, которые я выдергиваю из БД, то с'едается сразу 25МБ памяти. Т.е. как видно скоростью прийдется пожертвовать и развлекать узеров прогресс баром =)
 

_RVK_

Новичок
Poltoraki
А по частям не пробовал? То есть некий баланс памяти и скорости.
 

Poltoraki

Новичок
_RVK_
пробовал. Память конечно экономится, это без разговоров, а вот скорость все равно сильно не увеличиваеется. Если рекодрсет имеет 10х6315 значений, то по изначальному варианту все занимает около 20 сек, по самому быстрому - около 3-х, если по частям, то около 18 сек. Причем, как я заметил, там время растет далеко не линейно. Думаю, зто еще чуть поковыряюсь и остановлюсь все-таки на варианте по частям, там хоть на чуть, но быстрее.
 
Сверху