db_merge выбран как самый простой вариант.
-имеется шустрая файловая система, 32 ядра (2 xeon 26xx)
-обычная табличка без привязки к drupal
Имеем массив типа
1=>(1,2, 3)
2=>(3,4,5)
...
99999=>(x,z,y)
работает одно ядро
Как распределить по всем ядрам?
Комментарии
Первым делом нужно вместо пхп взять ЯП с нормальной поддержкой многопоточности.
А гугл молчит?
Так это особенность мускуля работать на одном ядре.
Причём тут db_merge?
Mysql может кушать все ядра, но для одного запроса - одно ядро. Один PHP-поток тоже живёт только на одном ядре.
Чтобы распараллелить запись данных Вам нужно несколько PHP процессов, потом разобраться с индексами которые перестраиваются после каждого insert'а, а потом Вы всё равно упрётесь в IOPS'ы. В MySql этим обычно не занимаются, если только вы не собираетесь лопатить миллиарды строк, но тогда, для бигдаты, Вы не верно выбрали базу.
@bsyomov поправь, если я не прав.
Всё верно. Каждый процесс php выполняется только на одном ядре, как и каждый запрос mysql.
Для масштабирования, если оно вообще нужно, можно использовать, например очередь сообщений и множество обработчиков.
Но обычно, когда возникает такая проблема, это изначально плохо продуманная архитектура. Возможно, надо было складывать данные в базу без объединения, или даже не в базу, например, и производить операции объединения реже, или что-нибудь ещё надо было сделать иначе...
У программиста есть проблема.
Он решил разобраться с ней с помощью потоков.
две проблемы. у есть него Теперь
Я делал через Мультикурл и json распаралеливание. эффект есть, но еще не тестировал, так как скорее уперся в БД.
На уровне подозрений есть ощущение что MySQL все потоки в очередь ставит, а некоторые операции держит в памяти, что приводит к дублям.
IOPS'ы я буду убирать докупкой ssd
Какую БД использовать с drupal?
Ну и Хулиган прав. Да. была проблема, начал паралелить, проблем стало намного больше.
Вот, примерно так паралелил, добился только увеличения скорости в два раза. Вроде как в диски уперся, а может БД...
<?php
/**
* Implements hook_menu().
*/
/*
function test_menu() {
$items = array();
$items['test-rest'] = array(
'page callback' => 'test_run_multiple',
'access callback' => TRUE,
'file' => 'inc/test.inc',
'type' => MENU_CALLBACK,
);
$items['test-rest-row'] = array(
'page callback' => 'test_run_row',
'access callback' => TRUE,
'file' => 'inc/test.inc',
'type' => MENU_CALLBACK,
);
return $items;
}
*/
//генерируем данные и выбираем способ обновления
function test_run_multiple() {
global $base_url;
$key = 'xxx';
$data = array();
for($i=0; $i<800;$i++) {
$data['key_'.$i] = array(
'td1'=>rand(100, 200),
'td2'=>rand(100, 200),
);
}
if($type) {
$start = microtime(true);
//Делим массив на части
$data_chunk = array_chunk($data, 100);
$sumbit_data = array();
foreach ($data_chunk as $id=>$data_row) {
$sumbit_data[]['data'] = array(
'url' => $base_url.'/test-rest-row/?key='.$key.'&data='.urlencode(json_encode($data_row)),
'id'=>$id
);
}
//Паралелим$result = test_multiCurl($sumbit_data);
return 'Время обновления бд с Распаралеливанием '.(microtime(true) - $start).' сек.';
} else {
$start = microtime(true);
foreach ($data as $key_row=>$row) {
test_db_megre($key_row,$row);
}
return 'Время обновления бд без распаралеливания: '.(microtime(true) - $start).' сек.';
}
}
//ОБновление части массива данных через multiCurl
function test_run_row() {
if($_GET['key'] !='xxx') {
exit('error key');
}
$data = drupal_json_decode($_GET['data']);
if(!empty($data)) {
foreach ($data as $key_row=>$row) {
test_db_megre($key_row,$row);
}
}
} //Распаралеливание процеса
function test_multiCurl($data, $options=""){
if(count($data)<=0) return False;
$handles = array();
if(!$options) // add default options
$options = array(
CURLOPT_HEADER=>0,
CURLOPT_RETURNTRANSFER=>1,
);
//$start = $data;
foreach($data as $k=>$row){
$options[CURLOPT_URL] = $row['data']['url'];
$opt = curl_setopt_array($ch{$k}, $options);
//var_dump($opt);
$handles[$k] = $ch{$k};
}
foreach($handles as $k => $handle){
$err = curl_multi_add_handle($mh, $handle);
}
do {
curl_multi_exec($mh, $running_handles);curl_multi_select($mh);
} while ($running_handles > 0);
foreach(
$data as $k=>$row){$data[$k]['error'] = curl_error($handles[$k]);
if(!empty($data[$k]['error']))
$data[$k]['data'] = '';
else
$data[$k]['data'] = curl_multi_getcontent( $handles[$k] ); // get results
$data[$k]['entity'] = $row['data']['id'];
// close current handler
curl_multi_remove_handle($mh, $handles[$k] );
}
curl_multi_close($mh);
return $data; // return response
} //Обновление строки в БД
function test_db_megre($key_row, $row) {
$query = db_merge('test')
->key(array(
'key_row' => $key_row,
))
->fields(array(
'td1' => $row['td1'],
'td2' => $row['td2'],
))
->execute();
}?>
У меня пока только один вопрос: Накой? Оптимизация ради оптимизации?