Как уменьшить время цикла

0

У меня есть таблица базы данных, насчитывающая около 4000 имен. Мне нужно прочитать их, прокрутить их и создать записи в другой таблице с этими именами вместе с идентификатором, который вводит пользователь. Может быть до 20 идентификаторов. Я написал этот код, но если он по-прежнему работает после трех минут, я остановил его. Я надеюсь, что есть способ закодировать его, чтобы сократить это время. Он будет находиться на общем сервере с максимальным временем выполнения 60 секунд, чтобы он не мог больше времени. Вот что у меня есть. Может ли кто-нибудь увидеть способ увеличить скорость?

    $mysql_query = "select id from main_table";
    $post = array('0' => 1, '1' => 2); //up to 20 entries
    $cnt = count($post);
    $str = '';

    while ($item = mysql_fetch_array($mysql_query)) {
      for ($i = 0; $i < $cnt; ++$i)  {
        $str .= "('" . $item['id'] . "', '" . $post[$i] . "'),";
      }    
    }  
    $str = substr($str, 0 -1);
    mysql_query("insert into next_table values" . $str );
Теги:
performance
loops

3 ответа

3
Лучший ответ

Вот одно решение, которое не требует циклы PHP и конкатенации строк вообще. Но для этого вам нужен PHP-код (слева как упражнение):

$post = array(1, 2, 3);

В этом:

SELECT 1 AS val UNION ALL
SELECT 2        UNION ALL
SELECT 3

И это один запрос, который вам нужно выполнить:

INSERT INTO next_table
SELECT main_table.id, userval.val
FROM main_table
JOIN (
    SELECT 1 AS val UNION ALL
    SELECT 2        UNION ALL
    SELECT 3
) AS userval

Спойлер:

$post = array(1, 2, 3);
$sql = array_reduce($post, function($acc, $value){
  $cur = $acc === "" ?
    sprintf("SELECT %d AS val", $value) :
    sprintf("\nUNION ALL SELECT %d", $value);
  return $acc . $cur;
}, "");
0

Вот новый код, основанный на ответе Салмана А. Это займет около 3 секунд. Отлично. Я отправляю новый код, если кому-то это понадобится в какой-то момент.

    $mysql_query = mysql_query("select id from main_table");
    $post = array('0' => 1, '1' => 2); //up to 20 entries
    $cnt = count($post);
    $str = '';

    if ($cnt == 1) {
        $str .= "SELECT " . $post[0] . " AS val ";
    } else {    
        $str .= "SELECT " . $post[0] .  " AS val UNION ALL ";

        for ($i = 1; $i < $cnt; ++$i) {              
            $str .= " SELECT " . $post[$i] . " UNION ALL ";
        }
        $str = substr($str, 0, -11);
    }

    $raw = "INSERT INTO next_table SELECT main_table.id, userval.val
      FROM main_table JOIN ( " . $str . " ) AS userval ";             

    mysql_query($raw);      
0

Если вы не найдете другого решения, как уменьшить время выполнения, т.е. любой вид оптимизации, то вы можете попытаться уменьшить количество обрабатываемых записей одновременно.

Сделайте блок количества id, который может быть обработан в пределах ограничения времени выполнения.

// get the very last inserted record from next_table
// and select reasonable amount of records from main_table to process
$mysql_query = "SELECT id FROM main_table 
WHERE id > (SELECT id FROM next_table MAX(id) LIMIT 1) 
LIMIT 500)"; // change the 500 to whatever

Затем вызовите сценарий столько раз, сколько есть данных, ожидающих обработки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню