Как реализовать фоновое / асинхронное кэширование с обратной записью в PHP? - PullRequest
5 голосов
/ 29 ноября 2008

У меня есть конкретная страница PHP, которая по разным причинам должна сохранять ~ 200 полей в базе данных. Это 200 отдельных операторов вставки и / или обновления. Теперь очевидное, что нужно сделать, это уменьшить это число, но, как я уже сказал, по причинам, которые я не буду беспокоить, я не могу этого сделать.

Я не ожидал этой проблемы. В MySQL операции выбора кажутся достаточно эффективными, а вставки / обновления - нет (для этого обновления требуется около 15-20 секунд, что, естественно, недопустимо). Я написал системы Java / Oracle, которые могут успешно выполнять тысячи вставок / обновлений одновременно (в обоих случаях работают локальные базы данных; MySQL 5 против OracleXE).

Теперь в чем-то вроде Java или .Net я мог бы довольно легко сделать одно из следующего:

  1. Записать данные в память кэш с обратной записью (т.е. знать, как сохранить в базе данных и может сделать это асинхронно);
  2. Запись данных в кэш в памяти и использовать PaaS (постоянство как Сервис) модель т.е. слушатель кеш сохранит поля; или
  3. Просто запустите фоновый процесс которые могут сохранить данные.

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

Есть ли другие способы решения этой проблемы?

Ответы [ 10 ]

2 голосов
/ 10 января 2009

Еще одно решение, которое вы можете использовать (вместо настройки mysql :)), - это использовать некоторый сервер JMS и драйвер соединения STOMP для PHP для асинхронной записи данных на сервер базы данных. ActiveMQ имеет встроенную поддержку протокола STOMP. И есть проект StompConnect , который является прокси-сервером STOMP для любого JMS-совместимого сервера (OpenMQ, JBossMQ и т. Д.).

2 голосов
/ 16 декабря 2009

mysql_query ('INSERT INTO tableName VALUES (...), (...), (...), (...)')

Выше приведенный запрос лучше. Но у нас есть другое решение для повышения производительности оператора вставки.
Выполните следующие шаги ..
1. Вы просто создаете CSV (файл с разделителями-запятыми) или простой текстовый файл и записываете все данные, которые хотите вставить, используя механизм записи файлов (например, класс FileOutputStream в Java). 2. используйте эту команду

LOAD DATA INFILE 'data.txt' INTO TABLE table2
  FIELDS TERMINATED BY '\t';

3, если вам не ясна эта команда, перейдите по ссылке

2 голосов
/ 30 ноября 2008

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

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

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

Конечно, другая возможность состоит в том, что ваши вставки работают медленно из-за таблиц экстремального размера или большого количества индексов - в этом случае вам следует соответствующим образом масштабировать сервер базы данных. Вставка большого количества строк в таблицу, индексы которой не помещаются в ОЗУ (или не имеет ОЗУ, правильно настроенного для использования для кэширования этих индексов), обычно становится довольно вонючей.

НО не пытайтесь найти способ усложнить ваше приложение, когда есть способ легко повернуть его, сохранив текущий алгоритм.

1 голос
/ 22 августа 2012

Обратите внимание, что если ваша таблица только для вставки (без удалений и без обновлений для столбцов переменной длины), то вставки не будут блокировать или блокировать чтение при использовании MyISAM.

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

Я использую это, и очищаю только старые записи ежедневно, после чего следует «таблица оптимизации».

1 голос
/ 29 ноября 2008

Посмотрите статистику для вашей базы данных, пока вы делаете вставки. Я предполагаю , что одно из ваших обновлений блокирует таблицу, и поэтому все ваши заявления ставятся в очередь, и вы испытываете эту задержку. Другая вещь, на которую стоит обратить внимание, - это создание / обновление вашего индекса, потому что чем больше у вас индексов в таблице, тем медленнее становятся все операторы UPDATE и INSERT.

Другое дело, что я думаю, что вы используете MYISAM (механизм таблиц), который блокирует всю таблицу при обновлении. Я предлагаю вместо этого использовать INNODB. INNODB медленнее для SELECT -запросов, но быстрее для INSERT и UPDATE, поскольку блокирует только строку, над которой он работает, а не всю таблицу.

1 голос
/ 29 ноября 2008

Вы можете обновить локальный кеш (надеюсь, memcached), а затем протолкнуть запросы на запись через beanstalkd .

0 голосов
/ 08 апреля 2012

вы можете использовать CURL с PHP для выполнения асинхронных манипуляций с базой данных.

Одним из возможных решений является разветвление каждого запроса в отдельный поток, но PHP не поддерживает потоки. Мы можем использовать функции PCNTL , но мне сложно их использовать. Я предпочитаю использовать это другое решение для создания форка и выполнения асинхронных операций.

См. Это

http://gonzalo123.wordpress.com/2010/10/11/speed-up-php-scripts-with-asynchronous-database-queries/

0 голосов
/ 22 января 2012

учитывайте это:

mysql_query('start transaction');
mysql_query('INSERT INTO tableName VALUES(...)');
mysql_query('INSERT INTO tableName VALUES(...)');
mysql_query('INSERT INTO tableName VALUES(...)');
mysql_query('INSERT INTO tableName VALUES(...)');
mysql_query('INSERT INTO tableName VALUES(...)'); 
mysql_query('commit;')
0 голосов
/ 29 ноября 2008

Как вы делаете вставки, вы делаете одну вставку на запись

mysql_query('INSERT INTO tableName VALUES(...)');
mysql_query('INSERT INTO tableName VALUES(...)');
mysql_query('INSERT INTO tableName VALUES(...)');
mysql_query('INSERT INTO tableName VALUES(...)');
mysql_query('INSERT INTO tableName VALUES(...)');

или вы используете один запрос

mysql_query('INSERT INTO tableName VALUES(...),(...),(...),(...)');

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

0 голосов
/ 29 ноября 2008

Я бы заподозрил проблему с вашими SQL-вставками - это действительно не должно занять много времени. Помогут ли подготовленные запросы? Вашему серверу mysql нужно больше памяти, выделенной для пространства клавиш? Я думаю, что нужно задать еще несколько вопросов.

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