У меня есть веб-сайт на основе базы данных, обслуживающий около 50 000 страниц.
Я хочу отслеживать каждое обращение к веб-странице / записи. Я сделаю это путем создания журналов, а затем их пакетной обработки один раз в день. Меня не беспокоит, как я буду выполнять пакетный процесс, только самый быстрый способ регистрации.
Как бы вы регистрировались, что, по вашему мнению, быстрее:
a) Используйте PHP для добавления в конец текстового файла журнала.
б) Используйте MySQL, чтобы ВСТАВИТЬ В неиндексированную таблицу журнала.






Я считаю, что в плоский файл будет быстрее писать.
В файл будет быстрее, но в БД будет лучше.
Использовать базу данных - это единственный разумный вариант. Даже если это займет немного больше времени. Как только вы начнете с файлов журналов, вы окажетесь на пути, который причинит вам боль - например, перемещение серверов, прав доступа к файлам, предотвращает балансировку нагрузки и т. д.
Если у вас открыта база данных, я думаю, что, вероятно, будет быстрее вставить одну строку.
Однако, учитывая всю эту производительность, единственный способ быть уверенным - это написать простой тест и измерить его ...
Обновление: я провел быстрый тест - и, конечно же, если вам нужно открывать и закрывать файл, он примерно такой же или медленнее, используя тест из 10000 строк:
Однако, когда у вас начинает работать несколько процессов, это замедляется, как показано ниже. Это с 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");
Действительно - однако я бы вообще не стал писать в файл журнала. Как только вы начнете делать такие вещи, как агрегирование и ротация, это становится своего рода процессом, который пойдет не так, как в первом случае, и с небольшой выгодой с точки зрения ЦП. Базы данных хороши для хранения и извлечения данных ....
OP здесь, мне это кажется убедительным в сочетании с отложенной вставкой
Я бы порекомендовал вам протестировать оба варианта с помощью нескольких тестовых примеров.
Я бы предположил, что плоский файл будет быстрее, b / c это действительно то, что делает БД - она просто записывает его в файл. Единственное преимущество, о котором я могу думать, заключается в том, что если база данных может работать одновременно, вы можете получить лучшие результаты.
Я бы использовал отложенную вставку в MySQL. Таким образом, вам не придется ждать окончания вставки.
Интересно, что я не слышал об этих отложенных вставках, они кажутся идеальными для регистрации.
За исключением того, что нет никакой гарантии, что они действительно вставят. В большинстве случаев они это сделают ... но, поскольку это ведение журнала, вы, вероятно, захотите знать об исключительных случаях даже больше, чем об обычных!
Это правда, что он не узнает, если вставка выйдет из строя. Но если журналы предназначены только для статистики по просмотру страниц, и у него уже есть соединение с базой данных, отложенная вставка должна быть хорошей. Если журналы для него критичны, то это не лучшее решение.
OP здесь, да, в моем случае это не важно, если INSERT не работает.
Честно говоря, тогда это хорошее решение для вас, особенно из-за простоты реализации. Вы теряете некоторую гибкость и надежность, но при этом значительно экономите время и сложность разработки. Проголосовали! :-)
Теперь это устарело! dev.mysql.com/doc/refman/5.6/en/insert-delayed.html
Все зависит от вашей инфраструктуры и ограничений. Если диск медленный, запись будет медленной. Если SQL-сервер отстает от запросов, вставка будет медленной. Плоский файл, вероятно, лучший вариант, но я бы написал ваш код или использовал существующий код (PEAR :: Log), чтобы вы могли изменить поставщика и метод хранения по своему желанию.
Вы можете попробовать оба способа, используя log4php, который поддерживает:
Что касается входа в файл, вы можете повысить производительность за счет буферизации запросов на запись.
Записать в файл. Поверните журналы.
Пакетная загрузка файла в базу данных по расписанию.
Есть много, много причин выбрать эту архитектуру - простота масштабирования (запись во многие журналы, загрузка их в базу данных), отсутствие зависимости от SPOF в базе данных (если что-то пойдет не так, вы просто накапливаете журналы на некоторое время) , возможность выполнять очистку и нетривиальный синтаксический анализ во время загрузки, не перегружая рабочие серверы, и многое другое.
Несколько соображений:
Как уже упоминалось, это зависит от множества вещей, таких как трафик, скорость диска и т. д. Вам нужно будет протестировать оба сценария.
При тестировании MySQL попробуйте MyISAM и INNODB. Теоретически Innodb будет работать лучше, поскольку у него есть блокировка на уровне строк.
Я сделал нечто подобное. Я регистрирую каждую запись в отдельном файле, затем у меня есть пакетный процесс, который захватывает файлы, помещает их в файл tar и выгружает их на центральный сервер журналов (в моем случае S3 :)).
Я генерирую случайные имена файлов для каждой записи журнала. Я делаю это, чтобы файлы не блокировались при вращении. Таким способом очень легко заархивировать / удалить.
Я использую json в качестве формата журнала вместо обычных файлов журнала, разделенных пробелами. Это упрощает синтаксический анализ и добавление полей в будущем. Это также означает, что мне проще написать запись для каждого файла, чем добавлять несколько записей для каждого файла.
Я также использовал log4php + syslog-ng для централизации ведения журнала в реальном времени. У меня есть журнал log4php в системном журнале, который затем пересылается в журналы на мой центральный сервер. Это действительно полезно для больших кластеров. Одно предостережение заключается в том, что существует ограничение на длину сообщений системного журнала, поэтому вы рискуете усечь более длинные сообщения.
Если это для сайта, управляемого базой данных, почему бы вам просто не использовать встроенные возможности ведения журнала Apache или IIS и подходящий инструмент отчетности, такой как AWStats и другие, всегда есть Гугл Аналитика
Я предпочитаю вести журнал AWStats и веб-сервера - по сути, вы все равно получаете его бесплатно - даже если вы не анализируете трафик, вы все равно можете подумать о том, чтобы самостоятельно проанализировать файл журнала доступа Apache для любой пакетной обработки, которую вам нужно выполнить.
Вам следует попробовать SQLite. Это даст вам как скорость записи в файл, так и мощность базы данных.
Я использовал SQLLite несколько раз для похожих вещей - случаев, когда я хочу иметь что-то в базе данных, но не в системной базе данных - это действительно отличное решение во многих отношениях, которое заслуживает более широкой известности.
Много лет назад я прочитал статью в C++ Users Journal о производительности входа в систему. Независимо от того, используете ли вы базу данных или файлы, лучше всего записывать неформатированные данные, которые могут быть «преобразованы» в значимые данные, когда (и, что более вероятно, если) вам нужно просмотреть журналы. Подавляющая часть затрат на ведение журнала связана с информацией о строках, которые записываются в место назначения, и большую часть времени эти затраты тратятся зря - журналы никогда не читаются.
Я могу найти ссылку на статью, если она будет вам полезна.
Если вы используете ведение журнала на основе файлов или ведение журнала на основе базы данных, самым большим ударом по производительности будет блокировка файлов / таблиц. По сути, если клиент A и клиент B соединяются в течение относительно небольшого периода времени, клиент B зависает, ожидая снятия блокировки файла / таблицы совпадений, прежде чем продолжить.
Проблема с файловым механизмом заключается в том, что блокировка файлов необходима для предотвращения повреждения ваших обращений. Единственный способ обойти это - реализовать очередь для отложенной записи в файл.
С ведением журнала базы данных вы можете, по крайней мере, делать следующее [MySQL с использованием MyISAM]:
INSERT DELAYED INTO `hits` ...
См. 12.2.5.2. INSERT DELAYED синтаксис для получения дополнительной информации.
устарело сейчас, согласно MySQL v5.6
Вот почему разные процессы должны записывать в разные файлы ... Агрегировать позже. Все, что вам нужно беспокоиться об открытии / закрытии, - это буферизация журналов при ротации файлов с интервалами записи в журнал (один раз в час, вероятно, подходит для такого рода нагрузки).