За последние 24 часа нас посетили 18227 программистов и 1596 роботов. Сейчас ищут 927 программистов ...

Как правильно построить скрипт

Тема в разделе "Прочие вопросы по PHP", создана пользователем rysalo4ka, 29 янв 2014.

  1. rysalo4ka

    rysalo4ka Новичок

    С нами с:
    29 янв 2014
    Сообщения:
    6
    Симпатии:
    0
    У меня есть определеный flow который я пытаюсь оптимизировать. Моя главная проблема это медлительность программы. Пользователи подключаются через token, remote connection и потому даже оптимизированный код бежит медленно. Пытаюсь понять, есть ли возможность построить сам процесс подругому, так как подход у меня был "в лоб", это мой первый проэкт в php.

    Проект - в БД находятся все данные нужные для работы. Пользователи получают каждый раз окно с данными каждой строчки в БД. Заходить могут сразу несколько пользователей, при начале работы над строчкой, она "закрывается" на пользователя. После просмотра данных, пользователь дает ответ и нажимает на submit получая следущею строку (если таковая существует)

    Как процесс работает:

    Initialize.php - queries the DB based on some algo. and prepares one row (or none if there is no more)

    View.php - shows the row content to the user and gives him a form to fill.

    Update.php - When the user clicks on submit from the view, this php updates the DB and calls initialize to have a new row prepared.

    Проблема в том что между нажатием на submit и до получения следущего VIEW могут пройти 2-8 секунд. Оптимизация queries снизила предедущее время 5-10 секунд на 2-8 но мне кажется и это много.

    Можно ли подойти к этому процессу иначе? Возможно ли готовить следущею строку в то время как пользователь смотрит на View?
     
  2. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Вы место проседания нашли? XDebug вам в помощь.
     
  3. rysalo4ka

    rysalo4ka Новичок

    С нами с:
    29 янв 2014
    Сообщения:
    6
    Симпатии:
    0
    Больше всего времени занимает конечно же Initialize с его 5 selects и 3 update
     
  4. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    зависит конечно от самого запроса и объема данных. но... индексы вы создавали?
    если нет то скорее всего правильное их создание ускорит запросы на порядок
     
  5. rysalo4ka

    rysalo4ka Новичок

    С нами с:
    29 янв 2014
    Сообщения:
    6
    Симпатии:
    0
    Создавала (на то что выбираю :))
    Сами query занимают от 1-1.5 секунд. А submit берет от 2-8. Вот и мучаюсь...
     
  6. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Я бы посоветовал погонять запросы сами по себе, к примеру есть такая штука как EXPLAIN. У мну к примеру недавно на выборке с довольно хитрыми связями из 4 таблиц, в каждой >50к записей произошел затык. Помогла разбивка на 3 последовательных запроса )
    Ваш же скрипт, вам виднее. В принципе можно, и кидать его в мемкэш, потом уже проверять есть ли там новая строчка или нет. Но это как мне кажется жуткий костыль, лучше уменьшить время выполнения самой выборки.
     
  7. rysalo4ka

    rysalo4ka Новичок

    С нами с:
    29 янв 2014
    Сообщения:
    6
    Симпатии:
    0
    Так в том то и дело что на мой взгляд упростить запросы помоему нельзя. Индексы сделала, все запросы- то что нужно без лишнего... Даже не знаю что делать.
     
  8. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Хорошо бы для начала на скрипт взглянуть )
     
  9. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Так ты телепатией воспользуйся ;)
     
  10. romach

    romach Старожил

    С нами с:
    26 окт 2013
    Сообщения:
    2.904
    Симпатии:
    719
    Я после откровений сноудена шапочку из фольги не снимаю. Хрен с ней с телепатией, главное что они мои мысли читать не могут ))
     
  11. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    а от нас что хотите тогда?
    невидя ваши запросы и код, помочь почти нереально. так как один корявый запрос вполне может сильно нагибать сервер, даже если выглядит несложным.
     
  12. rysalo4ka

    rysalo4ka Новичок

    С нами с:
    29 янв 2014
    Сообщения:
    6
    Симпатии:
    0
    Update.php

    Код (Text):
    1. <?php
    2. require('connection.php');
    3. require ('checkUser.php');
    4.  
    5. $task=$_POST['task_id'];
    6. $row=$_POST['row_id'];
    7. $uName=$_POST['user_name'];
    8. $PRD_ID=$_POST['PRD_ID'];
    9. $Catalog_ID=$_POST['Catalog_ID'];
    10.  
    11. if( $_POST['answer']==1 )
    12.     {
    13.         $query="UPDATE ecnmatchingdetails SET RowStatus=2,Agent='".$uName."' , VendorAnswer='Yes', VendorComment='".$_POST['comments']."' where TaskID=".$task." and RowId=".$row;
    14.         mysqli_query($con, $query);
    15.     }
    16.     else
    17.     {
    18.         if( $_POST['answer']==2 )
    19.         {
    20.             $query="UPDATE ecnmatchingdetails SET RowStatus=2,Agent='".$uName."' , VendorAnswer='No',VendorReason='".$_POST['reapost']."', VendorComment='".$_POST['comments']."' where TaskID=".$task." and RowId=".$row;
    21.             mysqli_query($con, $query);
    22.         }
    23.         else
    24.         {  
    25.             if( $_POST['answer']==0 )
    26.             {      
    27.                 $query="UPDATE ecnmatchingdetails SET RowStatus=0, Agent='' where TaskID=".$task." and RowId=".$row;
    28.                 mysqli_query($con, $query);
    29.             }
    30.         }
    31.     }
    32.  
    33. $query = "Update projects set LastUpdateDate ='".date('Y-m-d')."' where ProjectID=".$task;
    34. mysqli_query($con, $query);
    35.  
    36. if( isset( $_POST['answer'])) {
    37.         header( 'Location:..../WorkOnTaskECNMatching.php?id='.$task . '&start_task=0&Catalog_ID='.$Catalog_ID.'&prevID='.$PRD_ID.'&prevRow='.$row);
    38.         exit();
    39. }
    40.  
    41. ?>
    Добавлено спустя 3 минуты 31 секунду:
    Initial.php


    Код (Text):
    1. <?php
    2. require('connection.php');
    3. include 'checkUser.php';
    4.  
    5. $task_id=$_GET['id'];
    6. $start_task=$_GET['start_task'];
    7. $prevID=$_GET['prevID'];
    8. $EPID_finished=1; //this parameter will be 1 if we have another row with the same EPId or 0 if we dont have another row with this EPID
    9.  
    10. //updating the end tag of the previous row
    11. $time = date("Y-m-d H:i:s");
    12. if ($start_task==0){ //meaning we had a previous row because we came from submit
    13. $prevRow=$_GET['prevRow'];
    14. $query2="UPDATE ecnmatchingdetails SET end_tag='".$time."' where TaskID=".$task_id." and RowId=".$prevRow;
    15. mysqli_query($con, $query2);
    16. }
    17.  
    18.  
    19. /*********************************************** ECN "random" row choosing algorythm: **********************************************************/
    20. /*  1. Check if the user started working just now or came here from hitting the submit button
    21.     2. If it is a new user (start_task=1), choose a random row, that is "new" (not locked and not finished) and has an EPID that noone is working on it
    22.     3. If there is no such EPID, for us the user is done - he will see "task ended" even though there are unfinished rows
    23.     4. If the user already working (start_task=0, PRD_ID)- choose a row with the same EPID he had before
    24.     5. If there is no such EPID do number 2 and numer 3.
    25.    
    26.     ** The rows are grouped not only by EPId but also by a catalog
    27. ************************************************************************************************************************************************/
    28. $foundRow=0;
    29.  
    30. if ($start_task == 0){ //we came from a submit button and already worked on an EPID
    31.     $Catalog_ID=$_GET['Catalog_ID'];
    32.     $query = "SELECT * FROM ecnmatchingdetails WHERE TaskID=".$task_id."  AND PRD_ID=".$prevID."  AND RowStatus=0";
    33.     $data = mysqli_query($con, $query);
    34.     if (mysqli_num_rows($data) == 0)
    35.         $EPID_finished=0;
    36.     //We have some rows, now we need to choose one based on a catalogID.
    37.     else {
    38.  
    39.         while ($row = mysqli_fetch_array($data)){
    40.             if ($row['Catalog_ID']==$Catalog_ID){              
    41.                 $foundRow=1;
    42.                 break;
    43.                 }
    44.         }
    45.        
    46.         if ($foundRow==0) //we didnt find a row with a previous catalog ID
    47.         {
    48.             mysqli_data_seek($data, 0);
    49.             $row = mysqli_fetch_array($data);
    50.         }
    51.     }
    52. }
    53. if ($start_task==1 OR $EPID_finished==0){ //If this user just started working or this EPID has no more rows
    54.    
    55.     $Catalog_ID=NULL;
    56.     $query = "SELECT * FROM ecnmatchingdetails WHERE TaskID=".$task_id." AND RowStatus=0 AND PRD_ID NOT IN (
    57.                 SELECT DISTINCT PRD_ID FROM ecnmatchingdetails WHERE TaskID=".$task_id."  AND RowStatus=1)
    58.                 LIMIT 1";
    59.     $data = mysqli_query($con, $query);
    60.     $row = mysqli_fetch_array($data);
    61. }
    62.  
    63. /******************************************************************************************************/
    64. //lock the row we are working on
    65. $query="UPDATE ecnmatchingdetails SET RowStatus=1 ,Agent='".$_SESSION['username']."' where TaskID=".$row['TaskID']." and RowId=".$row['RowId'];
    66. mysqli_query($con, $query);
    67.  
    68. /******************************************************************************************************/
    69. if($row['COUNTRY_ID']!=null)
    70. {
    71.     $deal_id = $row['DEAL_ID'];
    72.     $deal_name = $row['NAME'];
    73.     $deal_URL =  $row['URL'];
    74.     $countryID =  $row['COUNTRY_ID'];
    75.     $Catalog_ID =  $row['Catalog_ID'];
    76.     $Catalog_NAME = $row['Catalog_NAME'];
    77.     $upc = $row['UPC'];
    78.     $mpn = $row['MPN'];
    79.     $brand = $row['BRAND'];
    80.     $ctlgID = $row['CTL_ID'];
    81.     $Catalog_name=$row['Catalog_name'];
    82.     $PRD_ID = $row['PRD_ID'];
    83.     $ProductURL = $row['PRODUCT_URL'];
    84.     $MatchingReason = $row['MATCHING_REASON'];
    85.     $LastSortedDate = $row['LAST_SORTED_DATE'];
    86.     $row_id = $row['RowId'];
    87.  
    88. /******************************************************************************************************/
    89.    
    90.     //EPID title
    91.     $VUrl = 'http://...../query?Vr=0.1&Qy=AND(EQ(ATTR(29),' . $row['PRD_ID'] . '))&Sp=&Nr=1000&Sk=0&Fl=6+6&Hx=no';
    92.     $str = file_get_contents($VUrl);
    93.     $str= str_replace(' ',' ',$str);
    94.     $parse = explode('  ',$str);
    95.     $EPIDtitle = $parse[1];
    96.  
    97.  
    98.     //Find this project type (ECN) details
    99.     $query = "SELECT * FROM projecttypes JOIN projects ON projecttypes.TypeID=projects.ProjectType WHERE projects.ProjectID=".$row['TaskID'];
    100.     $data = mysqli_query($con, $query);
    101.     $row_2 = mysqli_fetch_array($data);
    102.  
    103.     $task_type =$row_2['TypeName'];
    104.     $question=$row_2['ProjectQuestion'];
    105.  
    106.     $reasons=explode(',',$row_2['ValidReasons']);
    107.     $reasonsHtml="";
    108.     for ($i = 0; $i <= sizeof($reasons)-1; $i++) {
    109.         $reasonsHtml .= "<option value='v".($i+1)."'>".$reasons[$i]."</option>";
    110.     }
    111.  
    112.     $answers=explode(',',$row_2['ValidAnswers']);
    113.     $answer_true= $answers[0];
    114.     $answer_false= $answers[1];
    115.     $answer_skip=$answers[2];
    116.  
    117.     $guideurl=$row_2['GuidelinesURL'];
    118.  
    119. }
    120.  
    121. //no rows left to answer
    122. else
    123. {
    124.     $query= "Select ProjectStatus from projects where ProjectID=".$task_id;
    125.     $stat = mysqli_query($con,$query);
    126.     $stArr = mysqli_fetch_array($stat);
    127.     if($stArr['ProjectStatus'] <= 2)
    128.     {
    129.         $query = "Update projects set FinishDate ='".date('Y-m-d')."', ProjectStatus='3' where ProjectID=".$task_id;
    130.         mysqli_query($con, $query);
    131.     }      
    132.     echo '<script>taskEnd();</script>';
    133. }
    134.  
    135. //updating the start tag of the new row
    136. $query="UPDATE ecnmatchingdetails SET start_tag='".$time."' where TaskID=".$task_id." and RowId=".$row_id;
    137. mysqli_query($con, $query);
    138.  
    139. switch ($row['COUNTRY_ID'])
    140. {
    141. case 1:
    142.   $linkToSite="http:/....";
    143.   break;
    144. case 44:
    145.    $linkToSite="...";
    146.   break;
    147. case 250:
    148.    $linkToSite="...";
    149.   break;
    150. case 36:
    151. $linkToSite="...";
    152. break;
    153. case 276:
    154. $linkToSite="....";
    155. break;
    156. default:   $linkToSite="....";
    157. }
    158. ?>
    Добавлено спустя 2 минуты 19 секунд:
    Так бы и сказали что хотите код увидеть :)
    А что я от вас хотела - я спросила - можно ли в PHP одновременно пока юзер видеть VIEW делать все query чтоб работало паралельно а не один скрипт за другим.
    Хотя уверена (или по крайней мере надеюсь) прочтя мой скрипт, вы найдете кучу других способов его улучшения :)
     
  13. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Одни дыры....
     
  14. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Да уж. В запросы вставляются не данные из POST, а переменные, скопированные из POST. Это, мягко говоря, не защита, а энтропия.
     
  15. rysalo4ka

    rysalo4ka Новичок

    С нами с:
    29 янв 2014
    Сообщения:
    6
    Симпатии:
    0
    Ваш ответ конечно же очень помогает :) Четко обьяснила проблему, приняли во внимания что я новичок, ответили на тот вопрос который я задала, прислали линк на возможное решение...
    У меня нет проблемы с защитой. Точнее - такого вопроса просто нет.
     
  16. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.251
    Адрес:
    там-сям
    прежде чем лечить, надо поставить диагноз.
    для начала надо узнать сколько времени выполняется каждый запрос. может статься, что у вас тупо соединение с базой устанавливается две секунды — такое тоже бывает из-за сетевых проблем.

    я бы посоветовал писать данные в файл лога.
     
  17. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Я бы посоветовал и уже советовал поставить XDebug и посмотреть, где идет проседание.