Небольшое вступление
Началом написания
серии статей "Советы и трюки" послужил отчет "Tips and Tricks" Расмуса Лирдофа
(Rasmus Lerdorf) с конференции PHPCon2002, которая
состоялясь 24 октября 2002 года в городе Milbrae, Калифорния, США. Изначально
планировалось просто перевести отчет по просьбам членов Клуба разработчиков PHP, но по
мере чтения статей возникло много спорных вопросов и разногласий с автором,
поэтому я постарался как можно более четко определить и разъяснить преимущества
и недостатки того, или иного подхода оптимизации решений.
Часть 1.
Оптимизация
1. Без необходимости не используйте регулярные
выражения.
В PHP кроме регулярных выражений существует большое
количество функций по обработке текста, которые в некоторых случаях могут
заменить их, экономя при этом ресурсы сервера.
Неправильно: <? $new
= ereg_replace("-","_",$str);
?>
Правильно: <? $new =
str_replace("-","_",$str); ?>
Неправильно: <? preg_match("/(\..*?)$/",$str,$reg);
?>
Правильно: <? substr($str,strrpos($str,));
?>
2. Используйте ссылки при обработке больших массивов данных для экономии
памяти сервера.
Работа со ссылками (references) является более
приемлемой при обработке больших объемов информации, хотя и немного медленней,
чем работа с копией, но использует меньший объем памяти. Поэтому Вы должны
самостоятельно определить, запасы каких ресурсов на сервере более рационально
использовать - процессора или памяти.
3. Постоянные (persistent) соединения с БД
Некоторые БД более медленно выполняют создание
новых соединений, чем другие БД. Чем дольше происходит создание нового
соединения, тем больший смысл имеет использовать постоянное соединение с БД. Но
учтите, что постоянные соединения связывают и используют ресурсы сервера, даже
тогда, когда эти соединения простаивают.
Учтите, в PHP реализована функция отключения
постоянных соединений, поэтому если у провайдера в конфигурации PHP установлена
директива mysql.allow_persistent = Off, то соединения вызываемые функцией
mysql_pconnect() будут обрабатываться как mysql_connect().
Очень часто встречаются советы не использовать
постоянные соединения с БД. Это связано в первую очередь с тем, что
многопоточные веб-сервера, к которым относится и Apache, не могут разделить со
своими потомками соединение с БД. Таким образом если следующий запрос приходит
на другого потомка, то он создает новое постоянное соединение, что со временем
приводит к появлению большого количества незакрытых соединений с БД и
переполнению допустимого лимита max_connections в MySQL. Возможно два решения
этой проблемы: первое описано выше заключается в запрете использования
постоянных соединений, второе - использовать малое значение времени жизни
постоянного соединения в директиве wait_timeout конфигурации MySQL. По умолчанию
оно составляет 28800 сек. (8 часов), по истечению которых после отсутствия
активности соединения будет закрыто.
Помимо всего этого существуют еще некоторые
проблемы постоянных соединений с транзакциями и блокировками таблиц. Так, если
таблица блокируется запросом на транзакцию или LOCK TABLE и при этом скрипт
заканчивает свое выполнение до завершения транзакции или выполнения
разблокировки таблицы UNLOCK TABLE соответственно, то вторичная попытка доступа
к таблице через это же постоянное соединение будет отклонена. При использовании
непостоянного соединения с БД, при завершении скрипта соединение закрывается
автоматически и при этом снимает блокировку со всех таблиц и завершает все
транзакции. Решением этой проблемы есть регистрации функции
register_shutdown_function() которая бы по завершению скрипта снимала блокировку
с таблиц и завершала транзакции.
Так что можете использовать, а можете и не использовать, все зависит от
поставленных задач.
4. Используешь MySQL? Проверь mysql_unbuffered_query()
Небуферезированные запросы к БД MySQL применяется
так же как и mysql_query(). Разница заключается в том, что вместо того, чтоб
ожидать полного окончания запроса сохранить результат в клиентском API,
небуферизированный запрос делает доступными результаты своего выполнения как
можно скорее, минуя буферизацию в клиентском API. Таким образом Вы получаете
боле быстрый доступ к данным с меньшими затратами памяти. Недостатком
использования такого типа запросов является невозможность получить доступ к
функции mysql_num_rows(),этои запросы медленнее на маленьких выборках SELECT, а
также хотелось бы заметить то, что при выполнении любого другого запроса, все
данные которые небыли выведены, будут потеряны.
5. В поисках идеала
Если решения выглядят для Вас комплексно, то наверняка найдется более простой
и очевидный подход к решению задачи.