|
| Дата |
|
USD/RUB | 93.4409 | BTC/USD | 64383.9410 |
|
|
|
Скрипты, программы и технические решения Обсуждаем скрипты, программы и новые технологии. |
23.04.2015, 01:01
|
#1
|
Senior Member
Регистрация: 03.08.2011
Сообщений: 803
Бабло: $272965
|
Обработка большого массива данных. 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 запросом и потом все считать уже пыхом, чтобы не грузить базу?
как правильно это делается, чтобы и сам пых не лег.
п.с. сам не кодер, так что не ругайтесь)
|
|
|
23.04.2015, 01:24
|
#2
|
Senior Member
Регистрация: 27.09.2013
Сообщений: 697
Бабло: $101520
|
Почему не сделать это одним запросом?
Код:
$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.
|
|
|
23.04.2015, 01:28
|
#3
|
Senior Member
Регистрация: 03.08.2011
Сообщений: 803
Бабло: $272965
ТС -->
|
ТС
Цитата:
Сообщение от editeur
И перед этим построить в базе составной индекс по camp_id и click_c2, если его еще нет.
Пых скорее всего ляжет быстрее быстрее, чем mysql.
|
таблицу я изменять не могу.
базе тяжко потому что там она считает много, не потому что это делается в 3 запроса.
нужно забрать сырые данные по быстрому и свалить с базы)
|
|
|
23.04.2015, 01:35
|
#4
|
Senior Member
Регистрация: 27.09.2013
Сообщений: 697
Бабло: $101520
|
А другую таблицу создать можешь?
Есть вариант сделать денормализацию и подсчитывать эти агрегаты при каждой вставке. Например создать еще одну таблицу, в ней составной 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)
|
|
|
23.04.2015, 01:38
|
#5
|
автоматизирую интернеты
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,362
Бабло: $470735
|
Цитата:
Сообщение от sad_taliban
Обработка большого массива данных. Есть таблица в базе, на 6кк строк.
|
это мало
Цитата:
Сообщение от sad_taliban
Нам нужно забрать, например 1кк записей пыхом и произвести манипуляции по ним.
|
очень глупая идея, такое делается исключительно средствами БД
Цитата:
Сообщение от sad_taliban
все эти подсчеты самим мускулом очень сильно тормозят базу.
|
это не проблема mysql и сам он ничего не тормозит.
Проблема в бизнес-логике запросов, а именно - в блокировках. Пока по таблице идет расчет, участвующие в расчете данные не должны изменяться, поэтому они блокируются на операцию write, все твое приложение (соседние коннекты) встают колом, т.к. все они ждут конца блокировки.
Какой используется тип таблиц? тут разница в том числе в типах блокировки и скорее всего у тебя MyIsam, у которого блокировка на всю таблицу сразу.
В момент подсчетов много соединений пытаются изменить эту таблицу? Можно ли отсрочить эти изменения оператором DELAYED ? Если нет, то либо делать копию таблицы, либо реплику поднимать, которую так и так неплохо бы иметь для бекапа.
И покажи схемы таблиц, а то вдруг там еще индексов нет по соответствующим полям.
|
|
|
23.04.2015, 02:25
|
#6
|
Senior Member
Регистрация: 03.08.2011
Сообщений: 803
Бабло: $272965
ТС -->
|
ТС
Цитата:
Сообщение от chesser
Какой используется тип таблиц? тут разница в том числе в типах блокировки и скорее всего у тебя MyIsam, у которого блокировка на всю таблицу сразу.
|
да, такой тип.
в таблицу пишется много записей, постоянно.
структуру базы я менять не могу, она такая как есть.
|
|
|
23.04.2015, 10:51
|
#7
|
Юниор
Регистрация: 06.02.2012
Сообщений: 1
Бабло: $1082
|
Для ускорения запросов на больших базах индекс строится.
Других вариантов здесь нет.
Запрос итак достаточно простой.
|
|
|
23.04.2015, 15:04
|
#8
|
автоматизирую интернеты
Регистрация: 05.07.2009
Адрес: chesser.ru
Сообщений: 3,362
Бабло: $470735
|
Цитата:
Сообщение от sad_taliban
да, такой тип.
в таблицу пишется много записей, постоянно.
структуру базы я менять не могу, она такая как есть.
|
причину тормозов я объяснил - блокировка всей таблицы на запись на момент время подсчета агрегирующими функциями (sum,count)
(Кстати, попробовать сменить тип таблицы myisam на innodb можно безболезненно одной командой, обратно тоже можно вернуть. Не уверен, что это даст результат, но я бы попробовал)
Еще остается вопрос по индексам таблицы.
Если со структурой текущих таблиц ничего нельзя сделать, то попробуй копировать эту таблицу в новую и в ней уже делай нужные расчеты. К новой таблице будет только один клиент обращаться на чтение, поэтому тормозить из-за блокировок не будет. Минус в том, что данные будут чуть-чуть искаженные, а именно на дельту, которая успела появится в момент копирования. В любом случае, этот способ намного гуманнее вытягивания данных из БД.
Последний раз редактировалось chesser; 23.04.2015 в 15:11.
|
|
|
27.04.2015, 02:02
|
#9
|
Senior Member
Регистрация: 03.08.2011
Сообщений: 803
Бабло: $272965
ТС -->
|
ТС
Попробовали копирнуть нужные нам строки в новую таблицу и по ней уже считать.
Опреация
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.
т.е. последний вариант по факту практически не блокирует таблицу.
|
|
|
|