:-)
  • SQL 01.12.2009

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

    CREATE TEMPORARY TABLE ids (value INT, url VARCHAR(255));
    INSERT INTO ids VALUES 
        (0, 'http://url1.ru'),
        (0, 'http://url2.ru'),
        (0, 'http://url3.ru');
    UPDATE blogs, ids SET my_value = ids.value WHERE blogs.url = ids.url;

    Поясню. Допустим, мне понадобилось обновить некое значение в таблице в соответствии с URL. Скажем, статистику интернет-магазинов. Я создал временную таблицу из тех значений, по котороым будет вестись поиск, и значений, которые я буду вставлять в нужную мне таблицу. Дальше, идет INSERT сразу нескольких строк. Его очень просто собирать в цикле из массива. Например вот так:

    $elements = array();
    foreach ($aray as $url => $value) {
        $elements[] = '('.$db->escape($value).', '.$db->escape($url).')';
    }
    $insert_string = implode(',', $elements);

    После чего, собственно апдейт со вставкой. Временная таблица исчезнет после окончания сессии БД. На то она и временная.

    А еще я писал про:

    1. Ошибка PDO Invalid Argument и Unix socket
    2. Тормозной SQLite? Совсем нет!
    3. Symfony: человеческое расположение админки

    Tags:

  • 10 комментариев

    WP_Modern_Notepad
    • Александр пишет:

      извиняюсь, что это даёт? увеличится производительность такого метода сохранения?

      да и при выполнении:

      INSERT INTO ids VALUES
      (0, ‘http://url1.ru’),
      (0, ‘http://url2.ru’),
      (0, ‘http://url3.ru’);

      сколько запросов 1 или 3 будет?

    • CharnaD пишет:

      Да. Скажем у нас 500 записей. 1 запрос будет выполняться значительно быстрее, чем 500 запросов, даже если этот один будет очень длинный.

      При таком комбинированном INSERT будет 1 запрос.

    • Snowcore пишет:

      Прикольно, надо будет попробовать!

    • Александр пишет:

      хм, интересно, спасибо за идею, надо будет по пробовать. Хотелось ещё дополнительно сократить кол-во запросов перерасчёте кол-во записей у родителей. Я рассказывать не буду, а просто сообщюу ссылку на одну из-за меток автора, про синхронизацию разделов
      http://kurilka.co.ua/archives/sync_counter_mysql/

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

      Спасибо вам

    • CharnaD пишет:

      Александр, в вашем случае я бы оставил вариант «UPDATE cats SET cats.cat_counter = ( SELECT COUNT(*) FROM items WHERE items.cat_id=cats.cat_id )». Потому что, чтобы собрать все данные, вам все равно придется сделать N запросов для подсчета, по количеству категорий. И вам все равно придется обновить каждую строчку таблицы. Так что использовать временную таблицу, я думаю ни к чему.

    • Александр пишет:

      да, можно и так, но давно я писал код, который собирает все разделы в один массив, и через рекурсию суммирует кол-во записей всех потомков, для этого лишние запросы не нужны, после суммирования, остаётся обновить счётчик(кол-во записей) только родителей, а вот ссылка на тот самый мой код
      http://narod.ru/disk/15328134000/_update_count.php.html

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

    • CharnaD пишет:

      Ну если так, то да.

    • Александр пишет:

      я просто к тому что если есть массив всех разделов, вся информация у нас уже и так имеется, нам остаётся только пробежаться рекурсией, и посчитать записей для родителей, лишних запросов делать не нужно, дальше остаётся только сохранить, для этого можно воспользоваться вашим примером(сохранением). Таким образом, мы уменьшим кол-во запросов во столько раз, сколько родителей.

    • Александр пишет:

      единственная проблема, это основной массив содержащий все данные о разделай, что может забивать буффер, но тут уже ничего не сделаешь, чем-то жертвовать приходится.

    • Nayjest пишет:

      хм, интересно конечно. Еще интереснее было бы потестить на больших таблицах, действительно ли это быстрее, ведь это в значительной части зависит от реализации движка БД

    Trackbacks

    Оставить комментарий

    Внимание: Комментарии проходят премодерацию. Не надо посылать их несколько раз.

    Это не спам.