У меня есть сайт с базой данных, обслуживающий около 50 000 страниц.
Я хочу отслеживать каждый веб-сайт / запись. Я сделаю это, создав журналы, а затем пакетную обработку журналов один раз в день. Меня не интересует, как я буду выполнять пакетный процесс, только с самым быстрым способом регистрации.
Как бы вы вошли в систему, что, по вашему мнению, быстрее:
a) Используйте PHP для добавления в конец текстового файла журнала.
b) Использовать MySQL для INSERT IN в неиндексированной таблице журналов.
Пишите в файл. Поворот журналов.
Пакетная загрузка файла в базу данных осуществляется по расписанию.
Существует много причин выбора этой архитектуры – простота масштабирования (запись во многие журналы, загрузка их на db), отсутствие уверенности в SPOF в базе данных (если что-то пойдет не так, вы просто скопируете журналы на некоторое время) , возможность делать чистку и нетривиальный синтаксический анализ во время загрузки без нагрузки на ваши серверы производства и многое другое.
Вы можете попробовать оба способа использовать log4php , который поддерживает:
Что касается входа в файл, вы можете повысить производительность за счет буферизации запросов на запись.
Я бы использовал Delayed Insert в MySQL. Таким образом, вам не нужно ждать завершения вставки.
Используйте базу данных – это единственный нормальный вариант. Даже если это займет немного больше времени. После того, как вы начнете с файлов журналов, вы окажетесь на дорожке, где это приведет к боли – например, перемещение серверов, разрешений файлов, исключение балансировки нагрузки и т. Д. …
Если у вас открыта база данных, я полагаю, что, вероятно, быстрее вставить одну строку.
Однако при всей этой производительности связанный единственный способ быть уверенным в том, чтобы написать простой тест и измерить его ….
Обновление: я сделал быстрый тест – и, конечно же, если вам нужно открыть и закрыть файл, это примерно такая же скорость или медленнее, используя тест из 10 000 строк:
Однако, когда вы начинаете выполнять несколько процессов, это замедляется, как показано ниже. Это связано с 10 параллельными процессами (все тайминги в секундах)
DB time: 2.1695 DB time: 2.3869 DB time: 2.4305 DB time: 2.5864 DB time: 2.7465 DB time: 3.0182 DB time: 3.1451 DB time: 3.3298 DB time: 3.4483 DB time: 3.7812 File open time: 0.1538 File open time: 0.5478 File open time: 0.7252 File open time: 3.0453 File open time: 4.2661 File open time: 4.4247 File open time: 4.5484 File open time: 4.6319 File open time: 4.6501 File open time: 4.6646 Open close file time: 11.3647 Open close file time: 12.2849 Open close file time: 18.4093 Open close file time: 18.4202 Open close file time: 21.2621 Open close file time: 22.7267 Open close file time: 23.4597 Open close file time: 25.6293 Open close file time: 26.1119 Open close file time: 29.1471 function debug($d) { static $start_time = NULL; static $start_code_line = 0; if( $start_time === NULL ) { $start_time = time() + microtime(); $start_code_line = $code_line; return 0; } printf("$d time: %.4f\n", (time() + microtime() - $start_time)); $fp = @fopen('dbg.txt','a'); fprintf($fp,"$d time: %.4f\n", (time() + microtime() - $start_time)); fclose($fp); $start_time = time() + microtime(); $start_code_line = $code_line; } function tfile() { $fp = @fopen('t1.txt','a'); for ($i=0;$i<10000;$i++) { $txt = $i."How would you log, which do you think is quicker:How would you log, which do you think is quicker:"; fwrite($fp,$txt); } fclose($fp); } function tfile_openclose() { for ($i=0;$i<10000;$i++) { $fp = @fopen('t1.txt','a'); $txt = $i."How would you log, which do you think is quicker:How would you log, which do you think is quicker:"; fwrite($fp,$txt); fclose($fp); } } function tdb() { $db = mysql_connect('localhost','tremweb','zzxxcc'); $select_db = mysql_select_db('scratch'); if (!$select_db) die('Error selecting database.'); for ($i=0;$i<10000;$i++) { $txt = $i."How would you log, which do you think is quicker:How would you log, which do you think is quicker:"; mysql_query("INSERT INTO tlog values('".$txt."')"); } } debug(""); tfile(); debug("File open"); tfile_openclose(); debug("Open close file"); tdb(); debug("DB");
Я бы поверила, что плоский файл будет быстрее писать.
Вы должны попробовать SQLite . Это даст вам как скорость записи в файл, так и мощность базы данных.
Я сделал что-то подобное. Я записываю каждую запись в отдельный файл, затем у меня есть пакетный процесс, который захватывает файлы, помещает их в tar-файл и загружает их на центральный сервер журнала (в моем случае S3 :)).
Я генерирую случайные имена файлов для каждой записи в журнале. Я делаю это, чтобы избежать блокировки файлов для вращения. Это очень легко архивировать / удалять таким образом.
Я использую json в качестве формата журнала вместо типичных файлов журнала с ограниченным пробелом. Это упрощает анализ и добавление полей в будущем. Это также означает, что мне легче писать запись в файл, чем добавлять несколько записей на файл.
Я также использовал log4php + syslog-ng для централизации ведения журнала в реальном времени. У меня есть log4php log to syslog, который затем пересылается в журналы на мой центральный сервер. Это действительно полезно для больших кластеров. Одно из предостережений заключается в том, что для сообщений syslog существует ограничение по длине, поэтому вы рискуете усечь более длинные сообщения.
Я прочитал статью в журнале пользователей C ++, много лет назад, о производительности loggin. Независимо от того, используете ли вы DB или файлы, лучше всего писать неформатированные данные, которые могут быть «завышены» в значимые данные, когда (и, более вероятно, если) вам нужно просмотреть журналы. Подавляющее большинство затрат на регистрацию – это информация о строках, которые записываются в пункт назначения, и большую часть времени, затрачиваемых на затраты, журналы никогда не читаются.
Я могу выкопать ссылку на статью, если она вам полезна.
Если вы используете ведение журнала на основе файлов или ведение журнала на базе базы данных, самым большим достижением производительности будет блокировка файлов и таблиц. В принципе, если клиент A и клиент B подключаются в течение относительно небольшого периода времени, клиент B застрял, ожидая, когда блокировка будет выпущена в файле / таблице хитов, прежде чем продолжить.
Проблема с файловым механизмом заключается в том, что блокировка файлов необходима для обеспечения того, чтобы ваши образы не повреждались. Единственный способ – это реализовать очередь для записи в файл с задержкой.
При регистрации в базе данных вы можете, по крайней мере, сделать следующее [MySQL, используя MyISAM]:
INSERT DELAYED INTO `hits` ...
См. 12.2.5.2. INSERT DELAYED Синтаксис для получения дополнительной информации.
В файл будет быстрее, но в БД будет лучше.
Я бы рекомендовал вам протестировать оба теста с несколькими тестовыми примерами.
Я бы предположил, что плоский файл будет быстрее, b / c, это действительно то, что делает DB – это просто запись его в файл. Единственное преимущество, о котором я могу думать, заключается в том, что база данных может работать одновременно, вы можете получить лучшие результаты.
Все зависит от вашей инфраструктуры и ограничений. Если диск медленный, запись будет медленной. Если SQL-сервер отстает от запросов, вставка будет медленной. Плоский файл, вероятно, лучший способ пойти, но я бы написал свой код или использовал существующий код (PEAR :: Log), чтобы вы могли по желанию изменить метод провайдера и хранилища.
Несколько соображений:
Как упоминалось выше, это зависит от множества вещей, таких как трафик, скорость диска и т. Д. Вам придется протестировать оба сценария.
При тестировании MySQL попробуйте как MyISAM, так и INNODB. Теоретически Innodb будет работать лучше, поскольку он имеет блокировку уровня строки.
Если это для сайта, управляемого базой данных, почему бы вам не использовать встроенные возможности ведения журналов Apache или IIS и подходящий инструмент отчетности, такой как AWStats и, кроме того, всегда есть Google Analytics
AWTSats и ведение журналов веб-серверов – это мое предпочтение – вы по существу получаете его бесплатно в любом случае – даже если вы не после анализа трафика, вы все равно можете сами проанализировать файл журнала доступа Apache для любой пакетной обработки, которую вам нужно выполнить.