быстрый каунтер показов

Тема в разделе "PHP", создана пользователем zaartix, 15 июл 2008.

Статус темы:
Закрыта.
Модераторы: latteo
  1. zaartix

    zaartix Постоялец

    Регистр.:
    15 май 2006
    Сообщения:
    73
    Симпатии:
    27
    [FONT=verdana, arial, helvetica]Подскажите плз как Вы обычно делаете счетчик показов, при условии, что нужно максимально уменьшить нагрузку, т.к. показов может быть огромное количество. Как по-вашему, лучше через файлы это организовать или через бд?

    имеются ввиду баннерные показы, т.е. надо считать сколько чьих показов было. Вот думаю через primary key и Update field=field+1 или через счетчик в файлах?

    Возможно есть другие, менее ресурсоемкие методы?

    как вариант еще - создавать в юзерских папках уникальные файлы (touch), потом их считать кроном
    [/FONT]
     
  2. gregzem

    gregzem

    Регистр.:
    21 окт 2007
    Сообщения:
    200
    Симпатии:
    63
    У обоих подходов есть + и -.

    На файлах flock будет лочить их постоянно и при высокой нагрузке отдача баннеров будет "залипать", пока файл не разлочится. Еще файлы неудобно обрабатывать (надо парсить вручную данные). Для меня на самом деле так и осталось загадкой (со времен работы с Perl) как быстро выполняется flock и не может ли здесь быть коллизии при высокой интенсивности обращений к файлу flock->write->..., что пока flock лочит хэндл у файла кто-то в этот момент просочится и тоже начнет его лочить. Эксперименты не проводил, но как-то было один раз, что содержимое текстового файла обнулилось, хотя честно делал exclusive flock.

    В БД удобно вести статистику, лочатся таблицы штатными средствами и пр. Но вот на счет того, что будет работать быстрее, чем через файл - тут есть сомнение. БД - те же файлы + накладные расходы на коннект, транзакции и пр.
     
  3. zaartix

    zaartix Постоялец

    Регистр.:
    15 май 2006
    Сообщения:
    73
    Симпатии:
    27
    Я сейчас реализовал так:
    PHP:
    $file $baseId.'/'.$adv_id.'_'.$key_id.'.'.uniqid();
    if (!
    touch('/cache/shows/'.$file)) {
        
    mkdir('/cache/shows/'.$baseId);
        
    touch('/cache/shows/'.$file);
    }
    $baseId - id сайта, на котором считаются показы
    $adv_id - id объявления
    $key_id - id ключевого слова, по которому показ был

    само файло пустое

    Дальше крон обрабатывает папки

    Какие в перспективе у этого метода подводные камни есть? И можно-ли это считать наиболее оптимизированным методом подсчета?
     
  4. Jeurey

    Jeurey

    Регистр.:
    13 сен 2006
    Сообщения:
    419
    Симпатии:
    576
    zaartix, сколько сижу на никсах и сколько хостингов повидал - нигде в корне не видел папки cache.

    Во вторых, папочку 'cache/shows/'.$baseId нужно бы проверять на writeable и при создании проверять записываемость родительской директории.

    А то кусками проверочность не рулит. Все-равно, что одевать презерватив, зная что у него 5 верхних сантиметров нет :)
     
  5. zaartix

    zaartix Постоялец

    Регистр.:
    15 май 2006
    Сообщения:
    73
    Симпатии:
    27
    1. cache - это точка монтирования винта на ReiserFS :ah:
    2. непонял, проверять возможность записи перед записью? В данном случае это гораздо тормознее, имхо.
    Тач возвращает false или true, если true - все ок, если false - либо нет папки, либо нет прав (возможность повтора имен файлов исключаю, т.к. крон отрабатывает каждые 30 минут). Права быть должны при любых раскладах, т.к. папка создавалась самим апачем. А вот отсутствие папки - да, возможно, поэтому и делаем mkdir. Но гораздо чаще будет ситуация, когда папка уже существует, т.е. вцелом скорость будет выше

    А вообще какой смысл делать проверки, если я создал специально папку /cache/shows и дал ей 0777 ?
    или я вообще не о том? :))

    Добавлено через 27 минут
    кстати это вообще отдельная тема оптимизации кода, иногда быстрее будет работать, если проверки делать задним числом.

    Вот пример из sql (правда используется класс для работы с бд, но по названию функций понятно что они делают :) :(
    PHP:
    foreach ($t as $adv_id=>$shows) {
        
    $sql "update stats set shows='$shows', clicks='$clicks' where baseId='$baseId' and adv_id='$adv_id' and clock='$date'";
        
    $n $db->affected_rows($sql);
        if (!
    $n) {
            
    $sql "insert into stats (baseId, adv_id, clock, shows, clicks) values ($baseId,$adv_id,'$date','$shows','{$clicks[$baseId][$adv_id]}')";
            
    $db->query($sql);
        }
    }
    этот ведь будет гораздо быстрее работать, нежели:
    PHP:
    foreach ($t as $adv_id=>$shows) {
        
    $sql "select count(*) as num from stats where baseId='$baseId' and adv_id='$adv_id' and clock='$date' ";
        
    $d=$db->fetch_array($sql);
        if (
    $d['num']) {
            
    $sql "update stats set shows='$shows', clicks='$clicks' where baseId='$baseId' and adv_id='$adv_id' and clock='$date'";
            
    $db->query($sql);
        } else {
            
    $sql "insert into stats (baseId, adv_id, clock, shows, clicks) values ($baseId,$adv_id,'$date','$shows','{$clicks[$baseId][$adv_id]}')";
            
    $db->query($sql);
        }
    }
    я прав? или план просрочен оказался? :)
     
  6. Jeurey

    Jeurey

    Регистр.:
    13 сен 2006
    Сообщения:
    419
    Симпатии:
    576
    только что проверил - нету ни на одном хосте :)
    Аха, сделай chmod или mkdir с кривыми правами без подавления ошибок И посмотри.
    PS: для справки, в среднем, операция запуска функции с подавлением ошибки в 7 раз дольше длится ;)

    По коду - аха, согласен. Делать запросы к БД в цикле - это очень разумно :D :D :D
    PPS: Строки в двойных кавычках - тоже не есть хорошо. На досуге подумай почему ;)

    PPPS: хоть с кем-то по оптимизации есть теперь спорить :D
     
  7. zaartix

    zaartix Постоялец

    Регистр.:
    15 май 2006
    Сообщения:
    73
    Симпатии:
    27
    1. ну файловая система ведь позволяет создавать папочки :)

    2.1. так откуда кривые права???? :) я своими руками создал папку и поставил нужные права. С ней уже ничего не случится.
    А что подразумевается под подавлением? error_reporting или @mkdir ? Если у меня error_reporting(0) везде стоит, разве это затормаживает любую функцию сразу в 7 раз????

    2.2 насчет запросов к бд.

    вот смотри, каждые 30 минут по крону я обхожу папки и удаляю файло, в итоге в памяти массив с данными по показам. Дальше надо запихать это в таблицу статистики.
    Как это возможно сделать без foreach ? С учетом, что таблица хранит данные по датам, т.е.

    baseId, adv_id, shows, clicks

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

    Двойные кавычки - если ты насчет длительности парсинга одиночных и двойных, то этим имхо можно пренебречь в пользу удобства, если строка вне цикла или внутри небольшого цикла.

    начет поспорить - я только "за", посты-то нужны :)
     
  8. Jeurey

    Jeurey

    Регистр.:
    13 сен 2006
    Сообщения:
    419
    Симпатии:
    576
    А кривые права - это если создал папочку ручками (владелец - FTP-юзверь), а скрипт не может ее трогать (владелец - NOBODY), если права не 777.

    Или, обратная ситуация - вот тебе сразу геморрой и необходимость на проверки. Пишешь класс-враппер для всего этого хозяйства и таскаешь с собой от проекта к проекту - зато сразу забываешь как в оригинале работает :)

    По запросам отвечу так: создай в цикле 1 запрос и исполни его . А-ля mysql_query('Insert into... ; Insert into ...; Insert into...')
     
  9. Miraage

    Miraage Angular/Laravel

    Регистр.:
    3 июн 2008
    Сообщения:
    230
    Симпатии:
    51
    PHP:
    session_start();
    $_SESSION['count_shows'] = 0;
    function 
    countShows() {
    if (
    $shows$_SESSION['count_shows']++;
    $count_s =& $_SESSION['count_shows'];
    return 
    $count_s;
    }
    попробуй модифицировать этот код, мне помог с числом просмотров новостей на сайте
     
  10. Jeurey

    Jeurey

    Регистр.:
    13 сен 2006
    Сообщения:
    419
    Симпатии:
    576
    Ггы. Зачем ссылка на сессию? Для справки: ссылки эффективно применять только для собственных типов (для нерусских: для своих объектов). Да и то - в PHP5 такая надобность отпала (читай спецификацию).

    Если в целях оптимизации делать, то твой вариант явно проигрывает этому:

    PHP:
    session_start();
        
        function 
    countViews() {
            isset(
    $_SESSION['counts'])? ++$_SESSION['counts']: $_SESSION['counts']=1;
        }
    }
     
Статус темы:
Закрыта.