2012-03-07 3 views
0

Im пытается импортировать данные json в mysql.My json-файл почти 3.7Mb и имеет почти 17k строк (тестовые данные действительных данных будут составлять около 65k строк). Но с моим скриптом очень медленно и требуется почти 8-9мин. Есть ли какой-либо быстрый способ импорта json-данных в mysql с интерфейсом прогресса php? И я пытаюсь добавить функцию выполнения и ее работы на данный момент.Большие данные Json для mysql

$veri=json_decode(file_get_contents('auctions.json')); 

      $sayi=count($veri->alliance->auctions); 
      $a=$veri->alliance->auctions; 
      $yuzde=round($sayi/100); 
      echo "<div id='tasiyici'>"; 
      $sql=$db->prepare("INSERT INTO auctions (id, auc, item, owner, bid, buyout, quantity, timeLeft) VALUES ('',?,?,?,?,?,?,?)"); 
      for ($i=0;$i<=$sayi;$i++){ 
       $sql->execute(array($a[$i]->auc,$a[$i]->item,$a[$i]->owner,$a[$i]->bid,$a[$i]->buyout,$a[$i]->quantity,$a[$i]->timeLeft)); 
       if($i%$yuzde=='0'){ 
        $y=$i/$yuzde; 

        if(($y*4+4)>"180"){$pos=40-(($y*4+4)-180); $color="color:#fff";} 
        if(($y*4+4)>=220){$pos=0;} 
        echo "<div class='rakam' style='background-position:-".$pos."px 0;".$color."'>%".($y+1)."</div>"; 
        echo "<div class='yuzde' style='width:".($y*4+4)."px;'></div>"; 
        ob_flush(); 
        flush(); 

       } 


      } 
      echo "</div>"; 

      echo "<br> $sayi data added."; 

CSS коды

<style> 
     body { 
      font-family:Arial; 
     } 
      #tasiyici { 
       width:400px; 
       height:17px; 
       display: block; 
       position: relative; 
       margin:50px auto; 
       background:#e3e3e3; 
       border-radius:5px; 
       overflow: hidden; 
       border:1px solid #ccc; 
      } 
      .yuzde { 
       height:17px; 
       display: block; 
       width:1px; 
       background:url("progressOverlay.png"); 
       position: absolute; 
       top:0; 
       left:0; 
       z-index:1; 
      } 
      .rakam { 
       width:40px; 
       height:16px; 
       display: block; 
       line-height:17px; 
       position: absolute; 
       left:50%; 
       top:0; 
       margin-left:-20px; 
       z-index:9999; 
       background:url("progressOverlay.png") -40px 0 #e3e3e3 no-repeat; 
       font-size:11px; 
      } 

     </style> 
+1

Вы можете попробовать вставить более одной строки для каждого исполнения, но я скептически отношусь к этому, если это будет иметь большое значение для подготовленных операторов. Я попытался бы вставлять по крайней мере 1% ваших данных за выполнение. Повторное использование «INSERT INTO» не будет иметь большого значения, так как ваша бутылочная горловина - это объем данных. Другой способ - преобразовать ваши JSON-данные и сделать массовый импорт, например http://stackoverflow.com/questions/2811096/mysql-bulk-insert-from-csv-data-files – Basti

+2

Значит, '$ sayi' может быть 65 000? Если это так, то 65 000 запросов выполняются. Возможно, вместо этого попробуйте выполнить запросы в партиях по 100 или 1000. Я не уверен, как это сделать с подготовкой/выполнением, но я бы просто начал с «вставлять в таблицы (ключи) значения (значения), (значения), (значения) ...' и т. Д. И продолжать добавлять »(значения), 'до тех пор, пока у вас не будет 100 или 1000 или что-то еще, а затем выполните это. Должно быть немного быстрее, потому что будет меньше соединений mysql (в зависимости от вашей настройки). партии 1000 сократят это до 65 запросов – Benno

+1

Спасибо, ребята, я попробую 1000 строк для 1 запроса. Я добавлю результаты здесь. – xuma

ответ

1

9 минут * 60 секунд = 540 секунд

17000/540 = ~ 30,5 записи в секунду при вставке

Потому что вы сделали не публикуйте конфигурацию вашего сервера, загружайте, ram и т. д., мы не можем напрямую поставить проблему в определенный момент, к сожалению. Так или иначе, 30,5 вставки/сек мало для серьезного сервера. Это очень выполнимо, конечно, потому что размер вашей строки не кажется большим.

Что вам нужно сделать, это сделать некоторые серьезные измерения. Например, нехватка объема памяти создаст проблемы. Кроме того, многие дорогостоящие индексы на столе замедляют вставку довольно сложно.

Если вы делаете это много раз (например, при загрузке пользователем), было бы разумно создать для него очередь, так как это займет какое-то время. Хотя вставки 17k должны выполняться в считанные секунды, а не минуты.

Существует много имеющейся документации об оптимизации MySQL для вставок, это общий обзор влияния на скорость: http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html

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

  1. Ручка вставки в процессе работе в фоновом режиме, как хроны, постоянный запущенный скрипт и т.д. Таким образом, загрузить данные, хранить его и фоновый процесс будет обрабатывать что. Возможно, создайте для него таблицу importjobs.

Каждый х записи, которые вы могли бы сделать что-то вроде этого:

UPDATE importjobs SET counter = :amountimported WHERE id=:jobid 
  1. скрипт дает вам ответ на статус. Получая сообщения о статусе, написанные фоновым скриптом.

    SELECT, счетчик/общее AS partdone, счетчик, в сумме содержат от importjobs WHERE ID =: JobId

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

В зависимости от скорости, которую вы получаете, вы можете решить, хотите ли вы обновлять каждые 5, 10, 20, 60 секунд или что угодно. Этот поиск довольно дешев, поэтому вы можете сделать это несколько раз. В основном потому, что таблица importjobs также очень мала.

+0

Извините за недостаток информации. Я работаю на местном и 8-9 минут не точное время. Сейчас я пытаюсь получить json-данные из api (http://eu.battle.net/auction-data/veknilash/auctions.json) и сохранение в виде json-файла. Чтение и генерация sql-файла, и я попытаюсь загрузить в mysql. (Пока не удается.) Является ли это истинным способом сделать это или мне нужна любая другая логика? если я смогу добиться успеха в этой части, я попытаюсь сделать это с информацией о ходе. – xuma

+0

Это нормально, это просто показывает, как вы можете измерить. Например, вы можете написать простой скрипт, вставляющий множество строк, чтобы иметь указание скорости. Как правило, я вижу на своих машинах разработки производительность намного меньше по сравнению с оптимизированными серверами, которые мы используем в производстве. Сначала измерьте код, иначе вы можете потратить много времени на неправильные вещи. –

0

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

редактировать Вот ссылка на страницу MySQL человек http://dev.mysql.com/doc/refman/5.1/en/load-data.html

+0

Спасибо за ответ, я, вероятно, буду использовать это для сейчас. Но все-таки я хочу увидеть прогрессию. – xuma

1

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

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

То, что я сделал, это создать контрольную таблицу, в которой хранится ключ данных или какой-либо уникальный идентификатор. Во время обработки задание считывает базу данных управления, чтобы определить, существует ли запись, если это так, просто перейдите к следующей записи, добавьте ее.

Я создал ограничитель количества записей, чтобы проверить нагрузку (скажем, ограничение на первые 100 записей), и с помощью этого инструмента я смог запустить php-скрипт на 5 открытых вкладках в своем браузере, чтобы эффективно создавать параллельную загрузку ,

Смежные вопросы