MySQL обновление происходит так медленно - есть ли более быстрый способ обновления данных? - PullRequest
3 голосов
/ 13 сентября 2011

Мне нужно обновить 2M * 2rows в базе данных mysql.

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

UPDATE processed 
SET number1=$row[1], number2=$row[2], timestamp=unix_timestamp()
where match (id) against ('\"$id\"' IN BOOLEAN MODE) limit 1

Это работает - но это занимает слишком много времени ...

У меня есть индекс (основной) на(id).

Я пытался использовать что-то еще, кроме (id), которое включено в полнотекстовый индекс (я использую Myisam) - это даже медленнее.

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

Есть ли более быстрый способ сделать это?Если я переключусь на innodb, это будет быстрее?(Даже если это не так, я думаю, что это может быть круто во время обновления, вся моя таблица не будет заблокирована).

Поскольку числа 1 и 2 являются числами, я собираюсь сгруппировать все (идентификаторы), которые имеютбыть обновленным до того же номера - это будет быстрее?

Есть ли способ настроить mysqld так, чтобы столбцы number1, number2 и id оставались в оперативной памяти, делая его более быстрым для доступа / обновления?

Любая идея приветствуется, так как я полностью потерян ...:)

edit: добавление примера кода, чтобы вы могли понять мою ситуацию:

foreach ($data_rows as $rows) {
  $row=explode(":", $rows);  // $row[0] info
                             // $row[1] new number1
                             // $row[2] new number2

 $query = $db->query("select * from processed where match (info) against ('\"$info\"' IN BOOLEAN MODE) limit 1");

   while ($line = $query->fetch_object())
 {
   $data[$line->hash]['number1']=$line->number1;
   $data[$line->hash]['number2']=$line->number2;
   $id=$line->id;
  }

  if (is_array($data[$info]))       {  // Check if we have this one in the database.
    // If the number is correct, no need to update.
     if (($data[$info]['number1'] != $row[1]) && ($data[$info]['number2'] != $row[2])) {
 $db->query("UPDATE processed SET number1=$row[1], number2=$row[2], timestamp=unix_timestamp() where id=$id");
print "updated - $info - $row[1] - $row[2]\n";
                                               }
                    }
else    {
print "$info not in database\n";
    }
                }   

shema:

CREATE TABLE `processed` (
  `id` int(30) NOT NULL AUTO_INCREMENT,
  `timestamp` int(14) DEFAULT NULL,
  `name` text,
  `category` int(2) DEFAULT '0',
  `subcat` int(2) DEFAULT '0',
  `number1` int(20) NOT NULL,
  `number2` int(20) NOT NULL,
  `comment` text,
  `hash` text,
  `url` text,
  PRIMARY KEY (`id`),
  FULLTEXT KEY `name` (`name`),
  FULLTEXT KEY `hash` (`hash`)
) ENGINE=MyISAM AUTO_INCREMENT=1328365 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

отредактируйте снова:

ANALYZE TABLE processed; очень помогли улучшить время моего UPDATEs.(свежие индексы!)

Добавит мои данные в другую таблицу и все равно присоединится к обновлению:)

Ответы [ 3 ]

1 голос
/ 13 сентября 2011

Вы выполняете команды 2M * 2 UPDATE.Это займет некоторое время ...

Я бы посоветовал вам сбросить содержимое файла во временную таблицу и затем запустить одну команду UPDATE.

Обновить

Вот как вы можете запустить один присоединенный UPDATE:

UPDATE processed 
inner join DumpTable on processed.id = DumpTable.id
SET number1=DumpTable.value1 , number2=DumpTable.value2, timestamp=unix_timestamp()
0 голосов
/ 13 сентября 2011

Посмотрите на:

http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html

750,000qps может немного ускорить процесс.

0 голосов
/ 13 сентября 2011

Ну а) Вы всегда должны дезинфицировать свои данные -

sprintf("UPDATE processed 
         SET number1=%d, number2=%d, timestamp=unix_timestamp() 
         WHERE match (id) 
         AGAINST ('%d' $id IN BOOLEAN MODE) limit 1",
         mysql_real_escape_string($row[1]),
         mysql_real_escape_string($row[2]),
         mysql_real_escape_string($id)
);

Также, если вы переключитесь на InnoDB, это может быть немного быстрее, однако, для многих это лучший вариант, чем вы.не блокируйте всю таблицу, над которой вы работаете, для каждого выполняемого вами ОБНОВЛЕНИЯ, вы блокируете только строку, которую вы обновляете.

Так что это наиболее определенно о чем подумать, пожалуйста, прочитайте следующую ссылку: http://www.kavoir.com/2009/09/mysql-engines-innodb-vs-myisam-a-comparison-of-pros-and-cons.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...