За последние 24 часа нас посетили 18736 программистов и 1705 роботов. Сейчас ищут 694 программиста ...

тормозит выгрузка XML заказов самописная...

Тема в разделе "MySQL", создана пользователем Roman_SE, 28 окт 2009.

  1. Roman_SE

    Roman_SE Активный пользователь

    С нами с:
    28 окт 2009
    Сообщения:
    24
    Симпатии:
    0
    Подскажите друзья, почему тормозит мой самописный скрипт по выгрузке в xml файл? должно летать, но на выборке больше 100 заказов уже несколько минут выгружается, а если 1000 выгружать то ваще можно повеситься.

    PHP:
    1. ob_start();
    2.  
    3. require('includes/application_top.php');
    4. require(DIR_WS_CLASSES . 'order.php');
    5.  
    6.  
    7. $order_status = $HTTP_GET_VARS['orderstatus'];
    8. $lastorder = $HTTP_GET_VARS['lastorder'];
    9.  
    10.  
    11. $display_order_status = $order_status;
    12. if ($order_status == "")
    13.         {
    14.         $order_status = 1;
    15.         }
    16. echo '<?xml version="1.0" encoding="windows-1251" ?>
    17. <Order_File>';
    18.  
    19. $query_status = "SELECT * FROM " . TABLE_ORDERS_STATUS . " where `orders_status_id` = $order_status AND language_id = $languages_id";
    20. $status_result = tep_db_query($query_status);
    21.         while ($row4 = tep_db_fetch_array($status_result))
    22.         {
    23.                 echo "(";
    24.                      $orders_status_name =  $row4['orders_status_name'];
    25.                 echo $orders_status_name;
    26.                 echo ")";
    27.         }
    28.  
    29.  
    30. // FORM THAT LETS YOU SELECT WHICH ORDER STATUS TO DISPLAY
    31. ?>
    32.  
    33.  
    34.  
    35. <?php
    36. if (!isset($lastorder))
    37.  { $lastorder=LASTORDER; }
    38. $query1 = "SELECT * FROM " . TABLE_ORDERS . " WHERE orders_status = $order_status and  orders_id > $lastorder and orders_id < $lastorder+300 ORDER BY orders_id DESC";
    39. $result = tep_db_query($query1);
    40.  
    41. while ($row = tep_db_fetch_array($result))    {
    42.  
    43.                             $customers_street_address = $row['customers_street_address'];
    44.                             $customers_city = $row['customers_city'];
    45.                             $customers_street2 = $row['customers_suburb'];
    46.                                 if ($customers_street2 === '') {
    47.                             $customers_street2 = 'n/a';
    48.                             }
    49.                             $customers_country = $row['customers_country'];
    50.                             $customers_email_address = $row['customers_email_address'];
    51.                             $customers_telephone = $row['customers_telephone'];
    52.                             $customers_id = $row['customers_id'];
    53.                             $customers_fax = $row['customers_fax'];
    54.                             $customers_postcode = $row['customers_postcode'];
    55.                             preg_match("/(.*?)([0-9].*)/", $customers_street_address, $customers_street_split);
    56.                             $delivery_company = $row['delivery_company'];
    57.                             $delivery_company = substr($delivery_company, 0, 30);
    58.                             $delivery_company = preg_replace('/&(?!\w{2,6};)/', '&amp;', $delivery_company);
    59.                                 if ($delivery_company === '') {
    60.                             $delivery_company = 'n/a';
    61.                             }
    62.                             $delivery_postcode = $row['delivery_postcode'];
    63.                             $delivery_country = $row['delivery_country'];
    64.                             $date_purchased = $row['date_purchased'];
    65.                             $Day = substr($date_purchased, 8,2);  
    66.                                           $Month = substr($date_purchased, 5, 2);
    67.                                             $Year = substr($date_purchased, 0, 4);
    68.                                             $Time = substr($date_purchased, 11);
    69.                                             $payment = $row['payment_method'];
    70.         $ordernummer = $row['orders_id'];
    71.         $delivery_name = $row{'delivery_name'};
    72.         $delivery_street_address = $row{'delivery_street_address'};
    73.         $delivery_city = $row{'delivery_city'};
    74.         $delivery_postcode = $row{'delivery_postcode'};
    75.         $customers_email_address = $row{'customers_email_address'};
    76.         $customers_telephone = $row{'customers_telephone'};
    77.         $query2 = "SELECT customers_firstname, customers_lastname
    78.                         FROM customers WHERE customers_id = $customers_id";
    79.                     $result2 = tep_db_query($query2);
    80.                     $row_cust = tep_db_fetch_array($result2);
    81.                     $customers_firstname = $row_cust['customers_firstname'];
    82.                     $customers_lastname = $row_cust['customers_lastname'];
    83.  
    84. $order = new order($ordernummer);
    85. $orders_history_query = tep_db_query("select orders_status_id, date_added, customer_notified, comments from " . TABLE_ORDERS_STATUS_HISTORY . " where orders_id = $ordernummer order by date_added");
    86. if (tep_db_num_rows($orders_history_query)) {
    87.       while ($orders_history = tep_db_fetch_array($orders_history_query)) {
    88.             $comments = tep_db_output($orders_history['comments']);
    89.       }
    90.     }
    91.    
    92.    
    93.                     $payment = $row{'payment_method'};
    94.                     $shiptaxt = $order->totals[1]['title'];
    95.                     $shiptax = $order->totals[1]['text'];
    96.                     $M_id = "CG";
    97.        
    98. echo "
    99.                     <Order>                        
    100.                     <Заказы>
    101.                     <Account_Ref>$M_id</Account_Ref>
    102.                     <Customer_ID>" . $M_id . "_$customers_id</Customer_ID>
    103.                     <Order_number>" . $M_id . "_$ordernummer</Order_number>
    104.                     <Date>$Day.$Month.$Year</Date>
    105.                     <Time>$Time</Time>
    106.                     <Delivery_Company_Name>$delivery_company</Delivery_Company_Name>
    107.                  <Delivery_Name>$delivery_name</Delivery_Name>
    108.                   <Street>$delivery_street_address</Street>
    109.                   <Street2>$delivery_suburb</Street2>
    110.                 <City>$delivery_city</City>
    111.                   <Postcode>$delivery_postcode</Postcode>
    112.                   <Payment>$payment</Payment>
    113.                   <Comments>$comments</Comments>
    114.                   <Shipping_Tax>$shiptax</Shipping_Tax>
    115.  
    116.                   </Заказы>
    117.                     <Клиенты>
    118.                     <Account_Ref>$M_id</Account_Ref>
    119.                     <Customer_ID>" . $M_id . "_$customers_id</Customer_ID>                     
    120.                     <Customer_Name>$customers_firstname $customers_lastname</Customer_Name>
    121.                     <Street>$customers_street_address</Street>
    122.                     <Street2>$customers_street2</Street2>
    123.                     <City>$customers_city</City>
    124.                   <Postcode>$customers_postcode</Postcode>
    125.                    <Country>$customers_country</Country>
    126.                   <Email>$customers_email_address</Email>
    127.                   <Tel>$customers_telephone</Tel>
    128.                   <Tel2>$customers_fax</Tel2>
    129.                                  </Клиенты>";
    130.  
    131.     echo "<Заказано>";
    132. //  <Order_number>$ordernummer</Order_number>
    133. //  <Customer_ID>$customers_id</Customer_ID>
    134.                  
    135.  
    136.  
    137.    for ($i = 0, $n = sizeof($order->products); $i < $n; $i++) {
    138.  
    139.                     $products_price = $order->products[$i]['price'];
    140.                                         $quantity_price = $order->products[$i]['qty'] * $products_price;
    141.                                         $products_model = preg_replace('/&(?!\w{2,6};)/', '&amp;', $order->products[$i]['model']);
    142.                                                 $model_name = $order->products[$i]['name'];
    143.                                                 $model_name = preg_replace('/&(?!\w{2,6};)/', '&amp;', $model_name);
    144.                                                 $product_qty = $order->products[$i]['qty'];
    145.  
    146.                        
    147.                                                 echo "
    148.                                                                                            
    149.                         <Line>
    150.                        
    151.                         <Model_Code>$products_model</Model_Code>                                                 
    152.                         <Model_Name>$model_name</Model_Name>
    153.                         <Unit_Price>$products_price</Unit_Price>
    154.                         <Quantity>$product_qty</Quantity>
    155.                         <Quantity_Price>$quantity_price</Quantity_Price>"; 
    156.              
    157.               //*******************************************
    158.                 //!!START MOD!!: Display Attribs
    159.                 //*******************************************
    160.                 //echo OL_MANU . '&nbsp;' . $mfg['manufacturers_name']."<br>";      //Doesn't work
    161.                 //echo OL_MODEL . '&nbsp;' . $order->products[$i]['model']."<br>";  //Doesn't work
    162.                 $j = 0;
    163.                 $colorset = 0;
    164.                 while ($products_options = $order->products[$i]['attributes'][$j]['option'])    {
    165.                     $products_options = $order->products[$i]['attributes'][$j]['option'];
    166.                     $products_options_values = $order->products[$i]['attributes'][$j]['value'];
    167.                     if ($products_options == "Оптическая сила")  {                        
    168.                                         echo "<PWR>$products_options_values</PWR>";
    169.                     }
    170.                     if ($products_options == "Радиус кривизны") {
    171.                                         echo "<BC>$products_options_values</BC>";
    172.                     }
    173.                     if ($products_options == "Цвет") {
    174.                                         echo "<Color>$products_options_values</Color>";
    175.                                         $colorset = 1;
    176.                     }
    177.                     if ($products_options == "Цилиндр") {
    178.                                         echo "<CYL>$products_options_values</CYL>";
    179.                     }
    180.                     if ($products_options == "Ось") {
    181.                                         echo "<AX>$products_options_values</AX>";
    182.                     }
    183.                     if ($products_options == "Форма") {
    184.                                         echo "<Color>$products_options_values</Color>";
    185.                                         $colorset = 1;
    186.  
    187.                     }
    188.  
    189.  
    190.  
    191.                     $j++;
    192.                 }
    193.                 If ($colorset != 1 and $j > 0) { echo "<Color>Прозрачный</Color>"; }
    194.                 echo "</Line>";
    195.                 //*******************************************              
    196.                 //!!END MOD!!
    197.                 //*******************************************
    198.             ?>
    199.  
    200. <?php
    201.  }
    202.  
    203.            
    204.          
    205.  
    206.  
    207.                
    208.          
    209.              
    210.                                            
    211. echo "</Заказано></Order>";
    212.  
    213.  
    214.  
    215.       }
    216.  
    217.  
    218. echo "</Order_File>";
    219. ?>
    220.  
    ну и далее идет уже разметка xml с тегами и переменными внутри них...
    Код (Text):
    1.  
     
  2. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Оформи - это читать невозможно. Это раз.

    А второе http://xdebug.org/docs/profiler - лекарство именно для твоего случая.
     
  3. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    no comments...


    А это что?

    Чтобы выяснить, что тормозит, ставьте таймеры (microtime) в основных функцональных блоках кода, так выясните, где конкретно появляются задержки.
    Из кода я ничего не понял: куда выгружаются xml-данные?
     
  4. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Kreker
    За прочтение мусора - тебе орден сутулого :) с закруткой на спине.

    А за это - штрафбат.
    Не учи плохому. Профилировщик сделает все то же самое, но лучше, полнее и нагляднее.
     
  5. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Да я по старинке... когда еще из дерева вырезали сайты...
     
  6. Roman_SE

    Roman_SE Активный пользователь

    С нами с:
    28 окт 2009
    Сообщения:
    24
    Симпатии:
    0
    А вот так если ? Этот скрипт запускается в oscommerce и использует некоторые его переменные...
     
  7. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Это предложение включить мод телепата? :)

    Ок. Буфер переполняется.

    UPD: Ага, теперь вижу. Специфика в выводе. Тут дело даже не в конкретно этом коде, а дело в подходе.
    Попробуйте вывести миллион раз строку "АБС" и увидите тормоза.
     
  8. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Это не сильно важно.

    Но на первый взгляд у тебя получается очень много запросов в цикле.
    Лучше вытащить $
    Код (Text):
    1. row = tep_db_fetch_array($result)
    за один раз все.

    Затем сформировать запрос сразу для всех выбранных $row
    Код (Text):
    1. $orders_history_query = tep_db_query("select orders_status_id, date_added, customer_notified, comments from " . TABLE_ORDERS_STATUS_HISTORY . " where orders_id = $ordernummer order by date_added");
    И потом уже в цикле сформировать xml.


    Хотя лучше будет обернуть его в функцию и нужные переменные передать как аргументы.
    И таки спили мушку :) Т.е. сделай профайлинг, он тебе скажет все намного точнее чем мы на форуме.
    А делается очень легко.
     
  9. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
  10. Roman_SE

    Roman_SE Активный пользователь

    С нами с:
    28 окт 2009
    Сообщения:
    24
    Симпатии:
    0
    cпасибо за подсказки, даже не знал что таки утилки есть ) пойду править руки.
     
  11. Roman_SE

    Roman_SE Активный пользователь

    С нами с:
    28 окт 2009
    Сообщения:
    24
    Симпатии:
    0
    Не, все таки я тупой ) Подскажите как переставить строчки чтоб циклы уменьшить?
     
  12. Roman_SE

    Roman_SE Активный пользователь

    С нами с:
    28 окт 2009
    Сообщения:
    24
    Симпатии:
    0
    просто зависает походу все таки не PHP а MYSQL когда делает select, тк в памяти именно mysql висит и жрет ее. может можно как-то аппаратно ускорить мускул? кеш побольше или еще что?
     
  13. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Не делать фиговы запросы?

    Сколько позиций выводится точно?
     
  14. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Я тебе подсказал.

    Выбрать все $row одним запросом в один общий массив. (mysql_fetch_assoc)
    Затем взять у них (в цикле у каждого) $ordernummer и записать в массив $ordernummerArray.

    Затем $orders_history_query выбрать тоже одним запросом
    [sql]' where orders_id IN (' . implode(',',$ordernummerArray) . ')'; [/sql]

    И последним циклом пробежаться по всем $row взять уже готовые данные из второго запроса и оформить в xml.
     
  15. Roman_SE

    Roman_SE Активный пользователь

    С нами с:
    28 окт 2009
    Сообщения:
    24
    Симпатии:
    0
    дык там же еще в конце таблица с товарами и хар-ками товаров поднимается на каждый заказ, я так думаю там тормозит то в основном... а первые 3 нельзя просто через left join объединить?
     
  16. Roman_SE

    Roman_SE Активный пользователь

    С нами с:
    28 окт 2009
    Сообщения:
    24
    Симпатии:
    0
    просто я вообще рекламой занимаюсь ))) а php постольку поскольку ковыряю... поэтому не особо в нем...
     
  17. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    а чего ночами не спать? Отдайте профессионалам...
     
  18. Roman_SE

    Roman_SE Активный пользователь

    С нами с:
    28 окт 2009
    Сообщения:
    24
    Симпатии:
    0
    да оно работает вроде коекак, вот и морочусь ...это все для загрузки в 1с нужно, 1с ник есть, а PHP профи нету.
     
  19. Roman_SE

    Roman_SE Активный пользователь

    С нами с:
    28 окт 2009
    Сообщения:
    24
    Симпатии:
    0
    поменял вот большую часть echo на переменную, а потом ее целиком вывожу, но там явно в запросе дело, таблица где-то 100тыс строк, видимо как он по ней начинает выборку делать, так ему плохо и становится.
     
  20. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Найдите аутсорсера/фрилансера.

    Код сам по себе жутковатый. Большую часть присвоений - выкинуть.
    Вложенные циклы можно развернуть.

    Время работы с O(n^2) сократится до N*O(n)
     
  21. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    База на 100к строк - это ерунда полная.

    У вас там для 1000 записей идет 1001 один запрос. Когда можно обойтись 2мя.
     
  22. Roman_SE

    Roman_SE Активный пользователь

    С нами с:
    28 окт 2009
    Сообщения:
    24
    Симпатии:
    0
    Поменял первый запрос на

    $query1 = "SELECT * FROM orders o left join customers c on c.customers_id=o.customers_id left join orders_status_history osh on osh.orders_id=o.orders_id WHERE o.orders_id > 1 and o.orders_id < 1000 and orders_status_id=1";

    тоесть первые три запроса в один склеил... по microtime замерил скорость - почти вообще не повлияло :( зато помогла переиндексация таблиц, почти в 2 раза быстрее стало исполнятся + вынес из дополнительного модуля orders только нужные запросы, еще пару секунд на 100 заказов.. но и все... на глаз все равно тормозит :) поставил denwer на ramdisk еще, тож чутка быстрее вроде бы. В итоге вместо 40 секунд где-то 17... но это на 100, а на 5000 уже полчасика где-то.
     
  23. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Да, жесть....
    ты ходил по этому линку?
    http://xdebug.org/docs/profiler
    Делал что я тебе говорил?

    Вот скажи мне пожалуйста. Ты читаешь что я пишу? Или мне можно заткнуться и не портить себе нервы?

    Ты в курсе какой запрос у тебя крутится тысячи раз?
     
  24. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Залей мне дамп базы куда-нибудь. Я тебе скажу сколько оно должно выполняться при правильном коде.
     
  25. Roman_SE

    Roman_SE Активный пользователь

    С нами с:
    28 окт 2009
    Сообщения:
    24
    Симпатии:
    0
    ну я так понимаю что он один раз грузится как массив и потом уже из этого массива строчки считываются,?? или я не прав?

    $query1 = "SELECT * FROM " . TABLE_ORDERS . " WHERE orders_status = $order_status and orders_id > $lastorder and orders_id < $lastorder+300 ORDER BY orders_id DESC";
    $result = tep_db_query($query1);

    while ($row = tep_db_fetch_array($result)) {

    Вот тут разве он повторяется???