Форум успешных вебмастеров - GoFuckBiz.com

  Форум успешных вебмастеров - GoFuckBiz.com > Бизнес-решения > Скрипты, программы и технические решения
Дата
USD/RUB59.1710
BTC/USD0.0000
Скрипты, программы и технические решения Обсуждаем скрипты, программы и новые технологии.

Закрытая тема
Опции темы Опции просмотра
Старый 23.04.2015, 01:01   #1
sad_taliban
Senior Member
 
Аватар для sad_taliban
 
Регистрация: 03.08.2011
Сообщений: 773
Бабло: $263625
Question Обработка большого массива данных. PHP+MySQL. Нужна помощь.

Парни, такое дело.
Есть таблица в базе, на 6кк строк.
Нам нужно забрать, например 1кк записей пыхом и произвести манипуляции по ним.
Пробуем так:

$domain_click=mysql_query("SELECT count(`click_c2`) from `mt_click` where `camp_id` = '$campid' AND `click_c2` = '$domains_a[0]'");
$land_click=mysql_query("SELECT SUM(`click_offer`) from `mt_click` where `camp_id` = '$campid' AND `click_c2` = '$domains_a[0]'");
$lead_click=mysql_query("SELECT SUM(`click_lead`) from `mt_click` where `camp_id` = '$campid' AND `click_c2` = '$domains_a[0]'");

все эти подсчеты самим мускулом очень сильно тормозят базу. как бы нам забрать сырых данных 1кк строк 1 запросом и потом все считать уже пыхом, чтобы не грузить базу?
как правильно это делается, чтобы и сам пых не лег.

п.с. сам не кодер, так что не ругайтесь)
sad_taliban вне форума  
Старый 23.04.2015, 01:24   #2
editeur
Senior Member
 
Регистрация: 27.09.2013
Сообщений: 620
Бабло: $89330
По умолчанию

Почему не сделать это одним запросом?
Код:
$result = mysql_query("SELECT count(`click_c2`) as click_count, SUM(`click_offer`) as sum_offer, SUM(`click_lead`) as sum_lead from `mt_click` where `camp_id` = '$campid' AND `click_c2` = '$domains_a[0]'");
$data=mysql_fetch_assoc($result);
echo $data['click_count'];
echo $data['sum_offer];
echo $data['sum_lead'];
И перед этим построить в базе составной индекс по camp_id и click_c2, если его еще нет.

Пых скорее всего ляжет быстрее быстрее, чем mysql.
editeur вне форума  
Старый 23.04.2015, 01:28   #3
sad_taliban
Senior Member
 
Аватар для sad_taliban
 
Регистрация: 03.08.2011
Сообщений: 773
Бабло: $263625
ТС -->
автор темы ТС По умолчанию

Цитата:
Сообщение от editeur
И перед этим построить в базе составной индекс по camp_id и click_c2, если его еще нет.

Пых скорее всего ляжет быстрее быстрее, чем mysql.
таблицу я изменять не могу.
базе тяжко потому что там она считает много, не потому что это делается в 3 запроса.
нужно забрать сырые данные по быстрому и свалить с базы)
sad_taliban вне форума  
Старый 23.04.2015, 01:35   #4
editeur
Senior Member
 
Регистрация: 27.09.2013
Сообщений: 620
Бабло: $89330
По умолчанию

А другую таблицу создать можешь?
Есть вариант сделать денормализацию и подсчитывать эти агрегаты при каждой вставке. Например создать еще одну таблицу, в ней составной Primary key(camp_id, click_c2) и три поля - click_count, sum_offer, sum_lead.
При вставке записи делать еще одну вставку в эту таблицу, что-то вроде
Код:
INSERT INTO denorm_table ( camp_id, click_c2, click_count, sum_offer, sum_lead) VALUES(:camp_id, :click_c2, :click_count, :sum_offer, :sum_lead)
ON DUPLICATE KEY UPDATE    
click_count = click_count+1, sum_offer = sum_offer + VALUES(sum_offer), sum_lead = sum_lead + VALUES(sum_lead)
editeur вне форума  
Старый 23.04.2015, 01:38   #5
chesser
автоматизирую интернеты
 
Аватар для chesser
 
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,382
Бабло: $470735
По умолчанию

Цитата:
Сообщение от sad_taliban
Обработка большого массива данных. Есть таблица в базе, на 6кк строк.
это мало

Цитата:
Сообщение от sad_taliban
Нам нужно забрать, например 1кк записей пыхом и произвести манипуляции по ним.
очень глупая идея, такое делается исключительно средствами БД

Цитата:
Сообщение от sad_taliban
все эти подсчеты самим мускулом очень сильно тормозят базу.
это не проблема mysql и сам он ничего не тормозит.
Проблема в бизнес-логике запросов, а именно - в блокировках. Пока по таблице идет расчет, участвующие в расчете данные не должны изменяться, поэтому они блокируются на операцию write, все твое приложение (соседние коннекты) встают колом, т.к. все они ждут конца блокировки.

Какой используется тип таблиц? тут разница в том числе в типах блокировки и скорее всего у тебя MyIsam, у которого блокировка на всю таблицу сразу.

В момент подсчетов много соединений пытаются изменить эту таблицу? Можно ли отсрочить эти изменения оператором DELAYED ? Если нет, то либо делать копию таблицы, либо реплику поднимать, которую так и так неплохо бы иметь для бекапа.
И покажи схемы таблиц, а то вдруг там еще индексов нет по соответствующим полям.
__________________
USA и NL серверы и VPS | wiki | блог | Drupal | NginxТДС
Ave, Google, morituri te salutant! © chesser
chesser вне форума  
Старый 23.04.2015, 02:25   #6
sad_taliban
Senior Member
 
Аватар для sad_taliban
 
Регистрация: 03.08.2011
Сообщений: 773
Бабло: $263625
ТС -->
автор темы ТС По умолчанию

Цитата:
Сообщение от chesser
Какой используется тип таблиц? тут разница в том числе в типах блокировки и скорее всего у тебя MyIsam, у которого блокировка на всю таблицу сразу.
да, такой тип.
в таблицу пишется много записей, постоянно.
структуру базы я менять не могу, она такая как есть.
sad_taliban вне форума  
Старый 23.04.2015, 10:51   #7
Process
Юниор
 
Регистрация: 06.02.2012
Сообщений: 1
Бабло: $1082
По умолчанию

Для ускорения запросов на больших базах индекс строится.
Других вариантов здесь нет.
Запрос итак достаточно простой.
Process вне форума  
Старый 23.04.2015, 15:04   #8
chesser
автоматизирую интернеты
 
Аватар для chesser
 
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,382
Бабло: $470735
По умолчанию

Цитата:
Сообщение от sad_taliban
да, такой тип.
в таблицу пишется много записей, постоянно.
структуру базы я менять не могу, она такая как есть.
причину тормозов я объяснил - блокировка всей таблицы на запись на момент время подсчета агрегирующими функциями (sum,count)

(Кстати, попробовать сменить тип таблицы myisam на innodb можно безболезненно одной командой, обратно тоже можно вернуть. Не уверен, что это даст результат, но я бы попробовал)

Еще остается вопрос по индексам таблицы.

Если со структурой текущих таблиц ничего нельзя сделать, то попробуй копировать эту таблицу в новую и в ней уже делай нужные расчеты. К новой таблице будет только один клиент обращаться на чтение, поэтому тормозить из-за блокировок не будет. Минус в том, что данные будут чуть-чуть искаженные, а именно на дельту, которая успела появится в момент копирования. В любом случае, этот способ намного гуманнее вытягивания данных из БД.
__________________
USA и NL серверы и VPS | wiki | блог | Drupal | NginxТДС
Ave, Google, morituri te salutant! © chesser

Последний раз редактировалось chesser; 23.04.2015 в 15:11.
chesser вне форума  
Старый 27.04.2015, 02:02   #9
sad_taliban
Senior Member
 
Аватар для sad_taliban
 
Регистрация: 03.08.2011
Сообщений: 773
Бабло: $263625
ТС -->
автор темы ТС По умолчанию

Попробовали копирнуть нужные нам строки в новую таблицу и по ней уже считать.
Опреация
mysql_query("CREATE TABLE `mt_click_` SELECT * from `mt_click` where `camp_id` = '$campid'");

выполнялась 46.3413 sec.

попробовали вытащить данные в переменную пхп.
операция
$domains=mysql_query("SELECT `click_c2`,`click_offer`,`click_lead` from `mt_click` where `camp_id` = '$campid' GROUP BY `click_c2`");
выполнялась 0.7126 sec.

т.е. последний вариант по факту практически не блокирует таблицу.
sad_taliban вне форума