Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Загрузка файлов в базу MySQL
 
 автор: DarkLord   (10.03.2006 в 11:30)   письмо автору
 
 

Есть задачка загружать log файлы в базу MySQL и, естественно,
делать выборки на основе этих данных.

Код загрузки данных на PHP:

<?php
$handle = fopen("$userfile", "r");
while (!feof($handle))
{
$buffer = fgets($handle);
$buffer=ltrim($buffer);
// ну и так далее
}
fclose($handle);
?>

Есть две системы, на которых проводилось тестирование:
1. Windows 2000Pro, Apache 2.0.52, MySQL 4.1.14, PHP 5.0.2
2. ALTLinux 2.4 Master & Apache, MySQL, PHP - стандартные
из дистрибутива.

Опытным путем было установлено, что на Windows log-файлы
размером больше 700 строк загружаются нестабильно, т.е.
может зарузиться от 700 до 1000 строк.
Более того скорость работы в Windows в разы больше по
сравнению с Linux.

Есть способ уравнять шансы обеих систем или поставить крест
на Windows, как платформу для подобного рода задач?


Александр aka DarkLord

   
 
 автор: Trianon   (10.03.2006 в 12:02)   письмо автору
 
   для: DarkLord   (10.03.2006 в 11:30)
 

А файлы локальные или удаленные?
Как-то очень слабо верится в то, что если более ничего не мешает, системе (любой!) не прочитать 1000 строк из файла.
Что там прячется в //ну и так далее ?

   
 
 автор: DarkLord   (10.03.2006 в 14:54)   письмо автору
 
   для: Trianon   (10.03.2006 в 12:02)
 

Файлы локальные - обмен по Ethernet.
Неважно, что прячется. Код ОДИНАКОВЫЙ выполняется на одной и той же машине, только на разных ОС. Мне тоже не верилось, пока сам не убедился.

   
 
 автор: Trianon   (10.03.2006 в 15:00)   письмо автору
 
   для: DarkLord   (10.03.2006 в 14:54)
 

Если бы такую задачу решал я, то наверное бы сделал чтение файла порциями по 64-128кБ, из порции забирал бы строки, и заносил из в базу одним оператором INSERT. И код скорее всего устойчиво работал бы на любой ОС. С разной скоростью - да. Но не ломался бы - точно.

   
 
 автор: DarkLord   (10.03.2006 в 16:15)   письмо автору
 
   для: Trianon   (10.03.2006 в 15:00)
 

А почему такие глюки есть предположение?

Т.к. это довольно серьезные нарекания и переписывать код только
для того, чтобы все работало под виндами нет никакого резона.
Для нормальной задачи всегда лучше выбивать отдельную машину,
а если машина отдельная, то выбор ОС очевиден.

   
 
 автор: Trianon   (10.03.2006 в 16:32)   письмо автору
 
   для: DarkLord   (10.03.2006 в 16:15)
 

>А почему такие глюки есть предположение?

Тут можно только гадать. В чем именно состоит глюк, помимо того, что скрипт не работает с длинными файлами, Вы не сообщили. В тех строках кода, которые Вы привели, всё чисто.

>Т.к. это довольно серьезные нарекания и переписывать код только
>для того, чтобы все работало под виндами нет никакого резона.

Безусловно, Вы сами будете решать, каким именно способом справляться с проблемой.
У меня и в мыслях не было навязывать Вам тот или иной путь.

   
 
 автор: DarkLord   (10.03.2006 в 17:03)   письмо автору
 
   для: Trianon   (10.03.2006 в 16:32)
 

>>А почему такие глюки есть предположение?
>Тут можно только гадать. В чем именно состоит глюк, помимо того, что скрипт не работает с >длинными файлами, Вы не сообщили. В тех строках кода, которые Вы привели, всё чисто.

В случае больших файлов загружает от 700 до 1000 строк, причем закономерность непонятна,
т.е. скрипт выполняется не до конца.

   
 
 автор: Trianon   (10.03.2006 в 17:50)   письмо автору
 
   для: DarkLord   (10.03.2006 в 17:03)
 

Это надо понимать так, что Вы включили все средства диагностики (error_reporting), но они не дали результата. Скрипт отрабатывает безо всяких сообщений и вываливается потому, что внезапно и неожиданно наступает условие feof($handle). Вот на этот момент и надо акцентировать внимание. Отсюда повторный вопрос.
Файл, который Вы открываете, действительно локальный? Т.е. размещенный на машине со скриптом, apache, PHP-интерпретатором и проч.? Или он живет где-то в локальной сети?
Тогда он, простите, удаленный.
Спрашиваю, потому что совершенно не понимаю, какой смысл поднимать еще один сервер, чтобы он собирал свои собственные логи. Других локальных у него нет и быть не может.

   
 
 автор: DarkLord   (13.03.2006 в 11:01)   письмо автору
 
   для: Trianon   (10.03.2006 в 17:50)
 

>Отсюда повторный вопрос.
>Файл, который Вы открываете, действительно локальный? Т.е. размещенный на машине со >скриптом, apache, PHP-интерпретатором и проч.? Или он живет где-то в локальной сети?
>Тогда он, простите, удаленный.
>Спрашиваю, потому что совершенно не понимаю, какой смысл поднимать еще один сервер,
>чтобы он собирал свои собственные логи. Других локальных у него нет и быть не может.

Файл пробовал как локальный, так и удаленный - результат один.
Отдельный сервер (статистики) создается для обработки лог-файлов другого сервера,
который занимается своей основной работой. Как попадают лог-файлы - это уже
дело десятое. Они вполне могут загружаться локально.

>Это надо понимать так, что Вы включили все средства диагностики (error_reporting), но они не дали >результата. Скрипт отрабатывает безо всяких сообщений и вываливается потому, что внезапно и >неожиданно наступает условие feof($handle). Вот на этот момент и надо акцентировать внимание.

А вот по поводу средств диагностики я бы не отказался от дельных советов, т.к. их не использую.

Я накатал тестовые скрипты, которые наглядно демострируют данную ситуацию.
Текущие эксперименты провожу на Windows.

Создаю тестовый лог-файл, на основе которого будет проводиться тестирование:


<?php
// предварительное удаление существующих таблиц
$query="drop table if exists sessions";
if(
$result=mysql_query($query)) echo "<br>Таблица sessions удалена.<br>";
else echo 
"<br><font color=red><b>Ошибка удаления таблицы sessions.</b></font><br>";

// создаем таблицы
$query="create table sessions (
id int unsigned not null auto_increment,
dat datetime not null default '0000-00-00 00:00:00',
num int not null,
primary key (id)
)"
;
if(
$result=mysql_query($query)) echo "<br>Таблица sessions успешно создана.<br>";
else echo 
"<br><font color=red><b>Ошибка создания таблицы session.</b></font><br>";

$handle fopen("test.txt""w");
$somecontent="13/03/2006 11:19:27 ";
$commentcontent="Здесь будут какие-то комментарии \n";
for(
$i=1$i<=1500$i++)
{
    
$tempcontent $somecontent;
    
$tempcontent .= "$i \n";
    if (
fwrite($handle$tempcontent)) echo "Строка номер $i записана.<br>";
    if (!
fmod($i20))
        if (
fwrite($handle$commentcontent)) echo "Комментарий записан.<br>";
}

fclose($handle);
?>


Для цикла 1500 получаем файл размером 40К, а для 150000 - 3,7М.

Путем экспериментов выяснено, что основную задержку при чтении лог-файла
вносит функция записи данных в MySQL.
Поэтому в этих тестах она закоментирована.


<?php
// ставим скрипт "на счетчик" (чтобы знать, как долго он выполнялся
$ttt=microtime();
$ttt=((double)strstr($ttt' ')+(double)substr($ttt,0,strpos($ttt,' ')));

$j=0;
$handle fopen("test.txt""r");
while (!
feof($handle))
{
    
$buffer fgets($handle);
    
$buffer=ltrim($buffer);
    
$mbuf=substr("$buffer",0,10);
    if (
ereg ("([0-9]{2})/([0-9]{2})/([0-9]{4})"$mbuf))
    {
        
$j++;
        list(
$day$month$year$hour$minute$second$num) = sscanf($buffer"%d/%d/%d %d:%d:%d %d");
        echo 
"Строка $j прочитана.<br>";

        
$isodate sprintf("%04d-%02d-%02d %02d:%02d:%02d"$year$month$day$hour$minute$second);

//        $query="insert into sessions (id, dat, num) values (null, '$isodate', '$num')";
//        if($result=mysql_query($query)) echo "Сеанс связи записан: $isodate $num <br>";
//        else echo "<font color=red><b>Ошибка записи сеанса связи.</b></font><br>";
    
}
}

fclose($handle);
echo 
"<br><br><b>Всего загружено $j сеансов.</b><br>";

// считаем, как долго работал скрипт
$ddd=microtime();
$ddd=((double)strstr($ddd' ')+(double)substr($ddd,0,strpos($ddd,' ')));

echo (
"<br>Время индексации: ".(number_format(($ddd-$ttt),3))." секунд<br>");
?>


Если раскомментировать функцию записи данных в базу MySQL, то ситуация повторяется -
скрипт до конца не доходит.

   
 
 автор: Trianon   (13.03.2006 в 11:18)   письмо автору
 
   для: DarkLord   (13.03.2006 в 11:01)
 

Так может скрипт просто слишком долго выполняется? У PHP по умолчанию на выполнение всего скрипта таймаут в 30 секунд.

   
 
 автор: DarkLord   (13.03.2006 в 12:28)   письмо автору
 
   для: Trianon   (13.03.2006 в 11:18)
 

Очень похоже на правду.
Если так, то для меня вывод очевиден: т.к. винду не заставить работать быстрее,
то буду делать только на Linux.

ЗЫ Как насчет отладчика? Как им пользоваться?

   
 
 автор: Trianon   (13.03.2006 в 14:09)   письмо автору
 
   для: DarkLord   (13.03.2006 в 12:28)
 

Мне стало грустно. Настолько, что я написал вот это:

<?php 
// ставим скрипт "на счетчик" (чтобы знать, как долго он выполнялся 
$ttt=microtime(); 
$ttt=((double)strstr($ttt' ')+(double)substr($ttt,0,strpos($ttt,' '))); 


$j=0$blk_factor 16384;
$handle fopen("test.txt""r");
$block ''$sep "\n";
while (!
feof($handle))
{
    
$block .= fread($handle$blk_factor);
//    $buffer=str_replace(array("\r", "\n"), array("#", $sep), $buffer);
    
$lines explode($sep$block);
    
$cnt count($lines);

    
$block $cnt <= || substr($block,-1,1) == $sep
                 
"" :   $lines[--$cnt];
    if(
$block != "")
       unset(
$lines[$cnt]);
    
$query="insert into sessions (dat, num) values ";  $rsep '';
    foreach(
$lines as $buffer)
    {
      
$buffer=ltrim($buffer);
      
$mbuf=substr("$buffer",0,10);
      if (
ereg ("([0-9]{2})/([0-9]{2})/([0-9]{4})"$mbuf))
      {
        
$j++;
        list(
$day$month$year$hour$minute$second$num) = sscanf($buffer"%d/%d/%d %d:%d:%d %d");
        
//echo "Строка $j прочитана.<br>";

        
$isodate sprintf("%04d-%02d-%02d %02d:%02d:%02d"$year$month$day$hour$minute$second);

        
$query .= "$rsep('$isodate', '$num')"$rsep ',';
      }
    }
    if(
$result=mysql_query($query)) echo "Сеансы связи записаны по : $isodate $num <br>";
    else echo 
"<font color=red><b>Ошибка записи сеанса связи.</b></font><br>";

}

fclose($handle);

// считаем, как долго работал скрипт 
$ddd=microtime(); 
$ddd=((double)strstr($ddd' ')+(double)substr($ddd,0,strpos($ddd,' '))); 

echo (
"<br>Время индексации: ".(number_format(($ddd-$ttt),3))." секунд<br>"); 
?>


Поглядите... поиграйте параметром blk_factor.
И подумайте, о том, что стоит сократить бешеную работу оценки синтаксиса строк.
Думаю, кое-какой эффект Вы увидите.

PS. Для отладки я использую echo '<pre>'; print_r($var); А под средствами диагностики имел в виду error_reporting = E_ALL в php.ini.

   
 
 автор: DarkLord   (13.03.2006 в 16:28)   письмо автору
 
   для: Trianon   (13.03.2006 в 14:09)
 

Спасибо за великолепный пример.
Действительно все заработало на отлично.
Не судите меня сильно строго - я начал программировать на PHP недавно,
и уровень у меня невысокий.

Тем не менее все вышеизложенное моего последнего мнения не меняет.

   
 
 автор: Trianon   (13.03.2006 в 16:53)   письмо автору
 
   для: DarkLord   (13.03.2006 в 16:28)
 

Сколько времени выполняется? При каком блок-факторе? На какого размера логе? Интересно же...
А PHP я тоже недавно изучаю. Так что у Вас тоже скоро все будет ОК :)

   
 
 автор: DarkLord   (14.03.2006 в 10:14)   письмо автору
 
   для: Trianon   (13.03.2006 в 16:53)
 

Докладываю. ;-)

Системник: процессор Celeron 1,7 Ghz, 384 Mb оперативки.

1-ая система: Windows 2000pro, Apache 2.0.52, MySQL 4.1.14, PHP 5.0.2
2-ая система: ALTLinux 2.4 Master, Russian Apache PL30.20, MySQL 4.0.20, PHP 4.3.9

Размера оперативной памяти в системе хватало.

Тестировал на лог-файлах след размерах:
1. 419 Kb, 15000 записей
2. 3,3 Mb, 113851 записей
3. 3,7 Mb, 129433 записей

Результаты тестирования (время работы скрипта в секундах):

1 2
1 1,9 1,25
2 15,3 10,00
2 16,8 11,00

Очевидны преимущества использования Linux.


DarkLord

ЗЫ Я и стремлюсь чтоб с PHP все было хорошо, но и желательно
получать от этой деятельности не только моральное удовлетворение.

   
 
 автор: Trianon   (14.03.2006 в 10:29)   письмо автору
 
   для: DarkLord   (14.03.2006 в 10:14)
 

По-моему, время выполнения в разных ОС отличается не на порядок. И даже не в разы. Так что выбор ОС жестко на этом аспекте не завязан, и его можно выполнять по другим критериям. Например, по удобству администрирования Вами, по уровню имеющегося опыта работы, или пр.

Попробуйте поиграть блокинг-фактором. Увеличить в 2-10 раз, уменьшить в 2-10 раз. Возможно, что при увеличении блокинг-фактора, скорость еще вырастет. Главное, не перестараться. Найти значение, при котором рост становится уже незначительным, и на нем работать. Это позволит и память сэкономить и время особо не тратить.

   
 
 автор: DarkLord   (14.03.2006 в 11:28)   письмо автору
 
   для: Trianon   (14.03.2006 в 10:29)
 

Если я не ошибаюсь, то Apache и MySQL первоначально создавались для Unix систем и, естественно, больше оптимизированы для них.
Могу накатать еще кучу тестов, на выборках из базы и пр. на которых будет видно это преимущество, но мне лень. А по поводу данного примера, то, конечно, выберу оптимальный размер блока, но уже ближе к завершению написания программы.

По поводу удобства администрирования (не говоря уже о надежности) я все чаще свой выбор делаю в пользу Linux..

   
 
 автор: cheops   (14.03.2006 в 14:24)   письмо автору
 
   для: DarkLord   (14.03.2006 в 11:28)
 

MySQL оптимизируется под каждую операционную систему отдельно... Более того в Windows (как в прочем и Linux) она себя чувствует лучше, чем даже в FreeBSD...

   
 
 автор: DarkLord   (02.05.2006 в 09:20)   письмо автору
 
   для: DarkLord   (10.03.2006 в 11:30)
 

> MySQL оптимизируется под каждую операционную систему отдельно...
> Более того в Windows (как в прочем и Linux) она себя чувствует лучше, чем даже в FreeBSD...

А где взять рекомендации (или статьи) по оптимизации работы MySQL под Windows ?

   
 
 автор: cheops   (02.05.2006 в 11:53)   письмо автору
 
   для: DarkLord   (02.05.2006 в 09:20)
 

А что хотите настроить и для каких целей?

PS Под новые вопросы лучше заводить новые темы в разделе MySQL

   
 
 автор: DarkLord   (02.05.2006 в 14:36)   письмо автору
 
   для: cheops   (02.05.2006 в 11:53)
 

Хорошо.
Сделал новую тему в разделе MySQL:
http://www.softtime.ru/forum/read.php?id_forum=3&id_theme=16911&page=1
Переношу обсуждение вопросов туда.

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования