Jump to content

Программист, помни!


homm
 Share

Recommended Posts

1) Групируйте INSERT'ы. Если есть некое хранилище, откуда берутся данные, складывайте их в массив, а потом добавляйте.

Пример не верный:

$master_record = file($master_file);
foreach ($master_record as $item) {
$item = explode("t", trim($item));
$item = "('".implode("', '", $item)."')";
mysql_query("INSERT INTO Table(/*поля*/) VALUES ".$item);
}

Пример верный:

$master_record = file($master_file);
foreach ($master_record as $item) {
$item = explode("t", trim($item));
$item = "('".implode("', '", $item)."')";
}
$master_record = implode(', ', $master_record);
mysql_query("INSERT INTO Table(/*поля*/) VALUES ".$master_record);

2) Не группируйте INSERT'ы больше тысячи, иначе мускуль может просто уйти в аут.

Развивая предыдущий пример:

$file = fopen($master_file, 'r');
while (!feof($file)) {
$i = 0;
$master_record = array();
while ($i < 1000 && !feof($file) ) {
$master_record[] = "('".implode("', '", explode("t", trim(fgets($file))))."')";
$i++;
}
$master_record = implode(", ", $master_record);
mysql_query("INSERT INTO Table(/*поля*/) VALUES ".$master_record);
}

3) LEFT JOIN работает в 10 раз бстрее, чем JOIN

до: UPDATE geotar_slave AS slave JOIN geotar_regions AS regs ON regs.region = slave.region SET slave.region_id = regs.id ? 28 сек.

после: UPDATE geotar_slave AS slave LEFT JOIN geotar_regions AS regs ON regs.region = slave.region SET slave.region_id = regs.id ? 3,7 сек.

4) UPDATE ? очень долго. Если происходит связанная вставка в несколько таблиц, лучше заранее вычислить все поля, потратив больше времени на обработке PHP и вставить по одному INSERT на каждую таблицу, чем сначала вставить а потом UPDATE'ом обновлять связи.

до: 1500 UPDATE на каждый элемент связанного списка по 0,7 сек = 1050 сек.

после: по 1,5 сек предварительных расчетов на каждую из 96-и тысяч элементов основной таблицы = 144 сек.

5) Используйте все имеющиеся данные.

Пример ? поиск для элемента другого элемента по некоторому условию:

foreach ($master_record as &$item) {
$row = 0;
foreach ($master_cache as $key => &$master) {
if ( /* какое-то условие, связывающее $master и $item*/ ) {
$row = $key;
break;
}
}
$item[] = $row;
}

В моем случае заранее было известно количество элементов $item для каждого мастера, поэтому найдя n-ое количество соответствий решил выкидывать мастеров:

foreach ($master_record as &$item) {
$row = 0;
foreach ($master_cache as $key => &$master) {
if ( /* какое-то условие, связывающее $master и $item*/ ) {
$row = $key;
$master['count']--;
if ( $master['count'] == 0 ) {
unset ($master_cache[$key]);
}
break;
}
}
$item[] = $row;
}

до: по 1,5 сек предварительных расчетов на каждую из 96-и тысяч элементов основной таблицы = 144 сек.

поcле: примерно 4 сек на все 96 тыс. элементов.

Итого: скрипт работающий 1200 сек стал работать меньше чем за 10. Оптимизация ? страшная весч.

ЗЫ если кому интересно: конвертил базу http://ipgeobase.ru/ в человеческий вид.

Link to comment
Share on other sites

В примере (1), да и (2) можно использовать:

LOAD DATA INFILE 'fileName'
INTO TABLE tableName
FIELDS TERMINATED BY 't'
(field1,field2)

будет и быстрее и удобней.

Спасибо. Но в данном случае мне данные нужны были и для обработки.

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy