Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: SQL - помогите, пожалуйста, с составление запросов

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
Klinch
Отправлено: 01 Июля, 2014 - 18:33:22
Post Id


Частый гость


Покинул форум
Сообщений всего: 214
Дата рег-ции: Июль 2012  


Помог: 0 раз(а)




Здравствуйте!
Имеется такой говнокод:

PHP:
скопировать код в буфер обмена
  1.  
  2. <?
  3. $start = microtime(true);
  4. $sum = 0;
  5.  
  6. require( "../../includes/db.php" );
  7. $prosq=mysql_query("SELECT `procent`,`level1` FROM `invest-settings`");
  8. $prorow=mysql_fetch_array($prosq);
  9. $procent=$prorow['procent'];
  10. $date = date("d.m.Y");
  11.  
  12. if($procent!=0 || $procent!="0")
  13. {
  14. if(mysql_query("UPDATE `accounts` SET `lastpay`=round(`credits`/'100'*'$procent',2), `credits`=round(`credits`+(`credits`/'100'*'$procent'),2) WHERE `banned`='0'"))
  15. {
  16.         $res=mysql_query("SELECT `lastpay`, `id` FROM `accounts`");
  17.         while($row=mysql_fetch_array($res))
  18.         {
  19.                 if($row['lastpay']>0) mysql_query("INSERT INTO `accr-logs` (`user`,`credits`,`date`) VALUES ('".$row['id']."','".$row['lastpay']."','$date')");
  20.                 $res1=mysql_query("SELECT `partnerid` FROM `referals` WHERE `referalid`='".$row['id']."' AND `level`='1'");
  21.                 if(mysql_num_rows($res1)>0)
  22.                 {
  23.                         $row1=mysql_fetch_array($res1);
  24.                         $l1=$row['lastpay']/100*$prorow['level1'];
  25.                         $l1=floatval($l1);
  26.                         $l1=round($l1, 2);
  27.  
  28.                         mysql_query("UPDATE `accounts` SET `credits`=`credits`+'$l1', `ppay`=round(`ppay`+'$l1',2) WHERE `id`='".$row1['partnerid']."'");
  29.                         mysql_query("UPDATE `referals` SET `payniki`=`payniki`+'$l1' WHERE `referalid`='".$row['id']."' AND `partnerid`='".$row1['partnerid']."'");
  30.                 }
  31.         }
  32. }
  33. }
  34.         mysql_query("DELETE FROM `block-ip` WHERE `id`>'0'");
  35.  
  36.         $t = microtime(true) - $start;
  37.         mysql_query("UPDATE `invest-settings` SET `testtime`='".round($t, 4)."'");
  38.         mysql_close();
  39.         echo round($t, 4);
  40. ?>
  41.  


Первый запрос:
CODE (SQL):
скопировать код в буфер обмена
  1. UPDATE `accounts` SET `lastpay`=round(`credits`/'100'*'$procent',2), `credits`=round(`credits`+(`credits`/'100'*'$procent'),2) WHERE `banned`='0'


Вполне устраивает. Очень быстро прибавляет нужную сумму к credits всех аккаунтов, у которых banned = 0.

А далее идёт говнокод... Выполняется запрос всех полей из таблицы accounts и всё это обрабатывается в цикле. т.е. на каждый аккаунт выполняется около 4 запросов. Всего аккаунтов 30000, т.е. в общем выполняется 120000 запросов, что меня оооочень не устраивает.

Знаю, что всё это можно сделать за 3-6 запроса. Но не так силен в SQL и прошу помощи в их составлении. Все данные, которых не достаточно - предоставлю.


CODE (SQL):
скопировать код в буфер обмена
  1. INSERT INTO `accr-logs` (`user`,`credits`,`date`) VALUES ('".$row['id']."','".$row['lastpay']."','$date')

Этот запрос добавляет информацию в таблицу логов. В самом первом запросе мы прибавили определенную сумму к `credits` каждого аккаунта и установили всем аккаунтам в `lastpay` эту сумму, которую прибавили. В этом запросе мы вписываем в таблицу accr-logs запись для каждого аккаунта тот самый lastpay и date. т.е. если аккаунтов 30000, то в конечном итоге будет выполнено 30000 запросов INSERT и в таблице accr-logs прибавится 30000 строк.

Хотелось бы этот запрос как-то оптимизировать, чтобы не нужно было совершать 30000 запросов. Быть может, нужно как-то объединить первый запрос на UPDATE и этот на INSERT. Но как?

(Отредактировано автором: 01 Июля, 2014 - 18:36:07)

 
 Top
EuGen Администратор
Отправлено: 01 Июля, 2014 - 19:12:34
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Опишите логику словами с примерами выборок (до/после), тогда станет понятнее, можно ли реализовать только на SQL


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Klinch
Отправлено: 01 Июля, 2014 - 19:21:46
Post Id


Частый гость


Покинул форум
Сообщений всего: 214
Дата рег-ции: Июль 2012  


Помог: 0 раз(а)




EuGen
Большое спасибо за ответ!

Первый запрос оптимизировал вот так:

mysql_query("INSERT INTO `accr-logs` (`user`,`credits`,`date`) SELECT `id`, `lastpay`, '$date' FROM `accounts` WHERE lastpay>0;");

CODE (SQL):
скопировать код в буфер обмена
  1. mysql_query("INSERT INTO `accr-logs` (`user`,`credits`,`date`) SELECT `id`, `lastpay`, '$date' FROM `accounts` WHERE lastpay>0;");


Теперь с этим всё работает... Все логи корректно вносятся меньше чем за 0.02 секунды


Но есть еще парочка запросов, которые требует вмешательства. А точнее:

CODE (SQL):
скопировать код в буфер обмена
  1.                        mysql_query("UPDATE `accounts` SET `credits`=`credits`+'$l1', `ppay`=round(`ppay`+'$l1',2) WHERE `id`='".$row1['partnerid']."'");
  2.                         mysql_query("UPDATE `referals` SET `payniki`=`payniki`+'$l1' WHERE `referalid`='".$row['id']."' AND `partnerid`='".$row1['partnerid']."'");



Примерно то-же самое, только с UPDATE. Скажите, пожалуйста, возможно ли применить примерно такую-же конструкцию запроса как выше с INSERT, только с UPDATE? Если нет, то я опишу всё подробнее. Спасибо!

(Отредактировано автором: 01 Июля, 2014 - 19:45:54)

 
 Top
Panoptik
Отправлено: 02 Июля, 2014 - 07:17:56
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2493
Дата рег-ции: Нояб. 2011  
Откуда: Одесса, Украина


Помог: 131 раз(а)






-----
Just do it
 
 Top
Klinch
Отправлено: 02 Июля, 2014 - 11:14:48
Post Id


Частый гость


Покинул форум
Сообщений всего: 214
Дата рег-ции: Июль 2012  


Помог: 0 раз(а)




Большое всем спасибо!

Из кучи говнокода получилось вот это, правда пришлось добавить 1 новое поле `lastpay` в таблицу `referals`:

CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. mysql_query("INSERT INTO `accr-logs` (`user`,`credits`,`date`) SELECT `id`, `lastpay`, '$date' FROM `accounts` WHERE lastpay>0");
  3.  
  4. mysql_query("UPDATE `referals`, `accounts` SET `referals`.`payniki`=round(`referals`.`payniki`+(`accounts`.`lastpay`/'100'*'$procref'),2), `referals`.`lastpay`=round(`accounts`.`lastpay`/'100'*'$procref',2) WHERE `referals`.`referalid` = `accounts`.`id`");
  5.  
  6. mysql_query("UPDATE `accounts`, `referals` SET `accounts`.`credits`=`accounts`.`credits`+`referals`.`lastpay`, `accounts`.`ppay`=`accounts`.`ppay`+`referals`.`lastpay` WHERE `accounts`.`id`=`referals`.`partnerid`");
  7.  


А если быть точнее:

PHP:
скопировать код в буфер обмена
  1.  
  2. <?
  3. $start = microtime(true);
  4. $sum = 0;
  5.  
  6. require( "../../includes/db.php" );
  7. $prosq=mysql_query("SELECT `procent`,`level1` FROM `invest-settings`");
  8. $prorow=mysql_fetch_array($prosq);
  9. $procent=$prorow['procent'];
  10. $procref=$prorow['level1'];
  11. $date = date("d.m.Y");
  12.  
  13. if($procent!=0 || $procent!="0")
  14. {
  15.         if(mysql_query("UPDATE `accounts` SET `lastpay`=round(`credits`/'100'*'$procent',2), `credits`=round(`credits`+(`credits`/'100'*'$procent'),2) WHERE `banned`='0'"))
  16.         {
  17.                 mysql_query("INSERT INTO `accr-logs` (`user`,`credits`,`date`) SELECT `id`, `lastpay`, '$date' FROM `accounts` WHERE lastpay>0");
  18.                 mysql_query("UPDATE `referals`, `accounts` SET `referals`.`payniki`=round(`referals`.`payniki`+(`accounts`.`lastpay`/'100'*'$procref'),2), `referals`.`lastpay`=round(`accounts`.`lastpay`/'100'*'$procref',2) WHERE `referals`.`referalid` = `accounts`.`id`");
  19.                 mysql_query("UPDATE `accounts`, `referals` SET `accounts`.`credits`=`accounts`.`credits`+`referals`.`lastpay`, `accounts`.`ppay`=`accounts`.`ppay`+`referals`.`lastpay` WHERE `accounts`.`id`=`referals`.`partnerid`");
  20.  
  21.         }
  22. }
  23.  
  24.         mysql_query("DELETE FROM `block-ip` WHERE `id`>'0'");
  25.  
  26.         $t = microtime(true) - $start;
  27.         mysql_query("UPDATE `invest-settings` SET `testtime`='".round($t, 4)."'");
  28.         mysql_close();
  29.         echo round($t, 4);
  30. ?>
  31.  


Еще раз всем спасибо!
Panoptik ссылка очень помогла, спасибо!
Чуть позже отпишусь за сколько теперь это всё обрабаытвает 30к аккаунтов)
(Добавление)
Все 30000 аккаунтов обрабатываются за 2.5 секунды => 12000 аккаунтов в секунду

Раньше было около 5 аккаунтов в секунду. Да здравствует SQL!

(Отредактировано автором: 02 Июля, 2014 - 11:25:18)

 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Напишите за меня, пожалуйста »


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



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB