как работать с массивом данных?

Тема в разделе "Как сделать...", создана пользователем danneo, 16 апр 2015.

  1. danneo

    danneo Честный

    Регистр.:
    13 ноя 2007
    Сообщения:
    1.421
    Симпатии:
    109
    Есть фирмы, например, 1000 штук. У каждой фирмы есть результат опроса в баллах (например, у каждой по 200 штук).
    Получается 200 000 записей.
    Мне нужно будет с этими результатами проводить вычисления.
    Придумал только два способа работы:
    1. сформировать многомерный массив
    PHP:
    arr['id_firm']
      [
    '0']['res'] = 4.6
      
    ['1']['res'] = 2.9
      
    ['2']['res'] = 5.7

    arr
    ['id_firm']
      [
    '0']['res'] = 4.6
      
    ['1']['res'] = 2.9
      
    ['2']['res'] = 5.7
    Но учитывая, что 200 000 записей, то какой-то весомый массив будет.

    2. сформировать файлы po_id_firm.txt для каждой фирмы свой, с названием фирмы (ее id). Далее, при переборе выборки из БД, данные складывать в эти файлы (добавляя в конец файла строку).
    Файлов будет много, но зато можно будет потом взять файл и создать из него массив.

    Или как еще можно сделать? Проблема в том, что я не разбираются в нагрузке, что будет быстрее, что тормозить.
    Вообще, планирую это делать либо на локальном ПК, делая выгрузку с сайта, либо на стороннем сайте (удаленно), чтобы не нагружать сам сайт.
     
  2. latteo

    latteo Эффективное использование PHP, MySQL

    Moderator
    Регистр.:
    28 фев 2008
    Сообщения:
    1.405
    Симпатии:
    1.185
    Какого рода вычисление будут проводиться?

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

    Вот кстати синтетический тест для создания массива на 200к элементов и заполнения рендомными значениями похожими на ваши.
    PHP:
    $arr range(0200000);
    array_walk($arr, function (&$val) {
      
    $val rand(099) / 10;
    });
    var_dump(    count($arr)    );


    var_dump(    memory_get_peak_usage(true)    );
    У меня в пике 18Мб памяти ест, если это допустимо то можно и одним файлом хранить.
     
  3. krivov

    krivov Постоялец

    Регистр.:
    24 дек 2007
    Сообщения:
    142
    Симпатии:
    19
    Если обрабатывать этот массив надо не постоянно и не критично реалтайм обновление аналитики, то 200000 чисел в массиве, то это не большие данные, чтобы их в одном массиве хранить. Хотя всё зависит ещё от того как вы это всё будете обрабатывать.

    Вот просто тест на сложение всех элементов:

    PHP:
    <?php

    $arr 
    = array();
    $mtime explode(" ",microtime());
    $tStart $mtime[1] + $mtime[0];

    echo 
    "Старт = " memory_get_usage()/1000000 "Мб. <br>";

    for (
    $i=0;$i<=1000;$i++) {
        
    $arr[$i] = array();
        for (
    $j=0;$j<=200;$j++) {
            
    $arr[$i][$j] = rand(0,10);
        }
    }

    echo 
    "Сформировали массив = " memory_get_usage()/1000000 "Мб. <br>";

    $sum 0;
    foreach (
    $arr as $firm) {
        foreach (
    $firm as $value) {
            
    $sum $sum $value;
        }
    }

    echo 
    "После обработки массива = " memory_get_usage()/1000000 "Мб. <br>";

    for (
    $i=0;$i<=100;$i++) {
        unset(
    $arr[$i]);
    }

    echo 
    "После удаления первых 100 элементов = " memory_get_usage()/1000000 "Мб. <br>";

    echo 
    "Пиковое значение = " memory_get_peak_usage()/1000000 "Мб. <br>";

    $mtime explode(" ",microtime());
    $mtime $mtime[1] + $mtime[0];
    $totaltime = ($mtime $tStart);

    echo 
    "Затрачено времени = " $totaltime " c. <br>";

    На выходе:
    Старт = 0.141888Мб.
    Сформировали массив = 17.411664Мб.
    После обработки массива = 17.411856Мб.
    После удаления первых 100 элементов = 15.669768Мб.
    Пиковое значение = 17.42508Мб.
    Затрачено времени = 1.2103190422058 c.
     
  4. latteo

    latteo Эффективное использование PHP, MySQL

    Moderator
    Регистр.:
    28 фев 2008
    Сообщения:
    1.405
    Симпатии:
    1.185
    Несколько замечаний, которые помогут вам писать более быстрый код:
    В php есть нативная http://php.net/manual/ru/function.array-sum.php которая будет работать быстрее прохода массива через цикл.
    Над microtime не надо делать explode, лучше сразу получить в нужном формате microtime(TRUE)
    Очень много времени тратится на создание и заполнение массива рендомными данными выполнять замеры по времени лучше после создания, поскольку у ТС эта операция будет отсутсвовать.
     
  5. krivov

    krivov Постоялец

    Регистр.:
    24 дек 2007
    Сообщения:
    142
    Симпатии:
    19
    спасибо, конечно. за кодревью :) смешно
    Тут не было задачи написать быстрый код и написать его быстро, а наоборот как-то сымитировать перебор массива и вычисления, понятно. что тут имитация ни о чём, но всё же.
     
  6. danneo

    danneo Честный

    Регистр.:
    13 ноя 2007
    Сообщения:
    1.421
    Симпатии:
    109
    С каждым результатом опроса будут проводиться различные статистические вычисления. Например, в зависимости от даты опроса, определить устаревание значимости, сумму таких опросов и сумму всех результатов по одной фирме. Потом сумму по всем фирмам всех результатов и всех баллов с учетом устаревания, среднее арифметическое и т.п.
    И все эти данные в БД хранить не вижу смысла. Завтра они уже устареют и нужно пересчитывать. Но вот результат всех вычислений нужно будет уже сохранить в БД.

    В общем, сначала нужно сформировать массив по каждой фирме. Далее будет вычисляться параметр и добавляться как элемент еще один массива в соответствующему результату. Т.е. у каждого результата голосования будет несколько элементов, например, балл, среднее арифм, сумму всех баллов, сумму кол-ва опросов и т.д.
    ['0']['res'] = 4.6
    ['0']['summ'] = 4.6
    ['0']['arifm'] = 4.6
    где 0 - результат опроса, а далее различные вычисления.
    Таким образом, массив получится в раз 5 больше, чем я указал :)

    Поэтому, я так думаю, что процесс будет выглядеть примерно следующим. Сформировать массив всех фирм, проходя по каждому элементу, будет считаться значения. Перебор массива будет примерно раза 3, наверно.

    Надеюсь, что описал, чего хочу :)

    Ладно, убедили :). попробую сделать в массиве. Спасибо.

    Еще, как вариант, если будет большая нагрузка, можно сделать запуск скрипта через крон. Выбирать по одной фирме и все ее результаты, и обрабатывать. Затем другую. Потом общие данные по всем фирмам останутся.


    А все же, Latteo, а что в БД сохранять в таком случае?
     
    Последнее редактирование: 16 апр 2015
  7. latteo

    latteo Эффективное использование PHP, MySQL

    Moderator
    Регистр.:
    28 фев 2008
    Сообщения:
    1.405
    Симпатии:
    1.185
    Подумалось мне, глядя на это
    PHP:
      ['0']['res'] = 4.6
      
    ['1']['res'] = 2.9
      
    ['2']['res'] = 5.7
    что это некие оценки, каждый день они прибавляются и их все надо хранить, при добавлении оценки пересчитывать некую статистику - в таком случае было бы лучше использовать БД
    Подсчитать при таком раскладе SQL запросом сумму или среднее будет гораздо быстрее чем каждый раз перечитывать файл и высчитывать это на php

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