- Використовуйте кешування опкодов
- Малюнок 1. PHP-запит
- Малюнок 2. PHP-запит, який використовує кеш опкодов
- Оптимізуємо конфігурацію PHP
- Що потрібно вимкнути
- Параметри, які потрібно включити або змінити
- Управляємо інструкціями require () s і include () s
- Оптимізуємо базу даних
- Помістіть базу даних на окрему машину
- Правильно проектують та індексує таблиці
- Аналізуємо виконуються на сервері запити
- Лістинг 1. Журнал повільних запитів в MySQL
- Лістинг 2. Результати інструкції EXPLAIN в MySQL
- Ефективно Кешуйте дані
- Лістинг 3. Приклад використання APC для кешування даних, отриманих з бази даних
- Висновок
- Ресурси для скачування
Архітектура LAMP лежить в основі багатьох Web-порталів, що обробляють мільйони запитів в день, таких як Wikipedia, Facebook і Yahoo! Цю архітектуру використовує безліч програмних пакетів, таких як Wordpress, Joomla, Drupal та SugarCRM, що дозволяють організаціям з легкістю розгортати Web-додатки.
Сила архітектури LAMP полягає в її простоті. У той час як стеки на основі технології .NET або Java ™ можуть вимагати потужного апаратного забезпечення, дорогих програмних стеків і складної настройки продуктивності, стек LAMP може працювати на рядовому «залізі» і використовувати програмні стеки з відкритим кодом. Так як програмний стек не є монолітним, а являє собою гнучкий набір компонентів, то настройка продуктивності може стати непростим завданням, адже кожен компонент вимагає індивідуального аналізу та настройки.
Однак є кілька простих аспектів, які можуть значно впливати на продуктивність Web-сайтів будь-якого розміру. У цій статті ми розглянемо п'ять рекомендацій щодо оптимізації продуктивності LAMP-додатки. Вони вимагатимуть дуже невеликих (якщо взагалі зажадають) змін архітектури вашого застосування, і тому є простими і безпечними способами оптимізувати час відгуку програми, а також вимоги до апаратного забезпечення.
Використовуйте кешування опкодов
Найпростіший спосіб підвищення продуктивності будь-якого PHP-додатки (звичайно ж, буква "P" в абревіатурі LAMP) - включити кеш опкодов. Я включаю його для всіх Web-сайтів, над якими я працюю, так як це дає великий виграш в продуктивності (часто час відгуку скорочується в два рази). Багато людей, які починають працювати з PHP, задають питання, що забезпечує таке серйозне поліпшення. Відповідь криється в тому, як PHP обробляє Web-запити. На малюнку 1 зображена схема виконання запиту в PHP.
Малюнок 1. PHP-запит
Оскільки PHP є мовою, що інтерпретується, а не компільовані, як, наприклад, C або Java, то вся процедура розбору-компіляції-виконання сценарію виконується для кожного запиту. На це витрачається чимало часу і ресурсів, навіть якщо сценарії рідко змінюються між запитами. Розібраний і скомпільований сценарій являє собою послідовність опкодов. Саме тут свою роль може зіграти кеш опкодов. У цьому кеші скомпільовані сценарії зберігаються у вигляді послідовностей опкодов, що дозволяє усунути етапи розбору і компіляції сценарію для кожного запиту. На малюнку 2 показана робота даної схеми.
Малюнок 2. PHP-запит, який використовує кеш опкодов
Таким чином, при наявності кешованих опкодов PHP-сценарію можна пропустити етапи розбору і компіляції і перейти безпосередньо до виконання опкодов і висновку результату. Алгоритм перевірки коректно обробляє ситуації, коли файл сценарію змінюється: при першому виконанні сценарію опкоди автоматично будуть перекомпіліровать і знову кешованими, щоб їх можна було використовувати для подальших запитів.
Кеші опкодов для PHP стали популярними вже давно; перші з них з'явилися ще в PHP V4. На сьогоднішній день є кілька широко використовуваних рішень, які знаходяться в активній розробці:
- Alternative PHP Cache (APC) є, можливо, найпопулярнішим механізмом кешування опкодов для PHP (див. ресурси ). Він розроблявся декількома провідними розробниками PHP; також в нього внесли вагомий вклад інженери Facebook і Yahoo !, що поліпшило його швидкість і стабільність. Він надає і деякі інші можливості поліпшення продуктивності обробки запитів в PHP, в тому числі компонент для кешування призначених для користувача даних, яке ми розглянемо далі в цій статті.
- Wincache - це механізм кешування опкодов, який найбільш активно розробляється програмістами команди Internet Information Services (IIS) компанії Microsoft®. Він призначений для використання виключно на системах Windows® з Web-сервером IIS (див. ресурси ). Він розроблявся з метою зробити PHP першокласної платформою розробки на стеку Windows-IIS-PHP, так як було відомо, що APC на цьому стеку працює не дуже добре. За функціональністю цей стек дуже схожий на APC; в ньому є компонент для кешування призначених для користувача даних, а також вбудований обробник сесій.
- eAccelerator - це відгалуження одного з початкових кешей PHP - Turck MMCache (див. ресурси ) .На відміну від APC і Wincache, він являє собою тільки кеш опкодов і оптимізатор; в ньому немає компонентів для призначеного для користувача кеша. Він повністю сумісний з стеками UNIX® і Windows і досить популярний на сайтах, в яких не використовується додаткова функціональність, що надається APC або Wincache. Воно актуальне в ситуаціях, коли для призначеного для користувача кешування використовується окремий сервер кешування, такий як memcache.
Без сумніву, кешування опкодов є першим кроком до прискорення роботи PHP за рахунок усунення необхідності розбору і компіляції сценарію при виконанні кожного запиту. Виконавши цей крок, ви повинні помітити скорочення часу оклику і зниження навантаження на сервер. Однак є й інші способи оптимізації роботи PHP, які ми розглянемо далі.
Оптимізуємо конфігурацію PHP
Включення кешування опкодов є важливим засобом поліпшення продуктивності, однак є й чимало інших можливостей оптимізації роботи PHP, заснованих на налаштуванні параметрів у файлі php.ini. Ці настройки більше підходять для робочого сервера, так як їх застосування в середовищі розробки або тестування може ускладнити налагодження додатків.
Розглянемо кілька аспектів, важливих для поліпшення продуктивності.
Що потрібно вимкнути
У файлі php.ini варто відключити кілька параметрів, які зазвичай використовуються для забезпечення зворотної сумісності:
- register_globals - за замовчуванням до PHP V4.2 змінні вхідного запиту автоматично поміщалися в звичайні змінні PHP. Крім серйозних проблем безпеки (пов'язаних із змішуванням неперевірених даних вхідного запиту зі звичайним вмістом PHP-змінної) це також створює додаткові витрати при обробці кожного запиту. Тому виключення цього параметра підвищить безпеку і поліпшить продуктивність вашої програми.
- magic_quotes_ * - цей параметр також є спадщиною PHP V4, він забезпечує автоматичне екранування даних, що надходять з форм. Ця функціональність замислювалася для цілей безпеки, щоб очистити вхідні дані перед їх відправкою в базу даних, однак її не можна назвати ефективною, так як вона не будемо захищати користувачів від найбільш типових видів SQL-ін'єкцій. Більшість баз даних підтримують підготовлені інструкції, які усувають цей ризик набагато краще. Тому для поліпшення продуктивності цей параметр можна вимкнути.
- always_populate_raw_post_data - цей параметр потрібен тільки в разі, якщо вам з якоїсь причини потрібно бачити всю робоче навантаження вхідного POST-запиту в нефільтроване вигляді. В іншому випадку дублікат даних POST-запиту буде просто зберігатися в пам'яті, тому цей параметр можна вимкнути.
У той же час відключення цих параметрів може становити ризик для старого коду, так як він може покладатися на те, чи правильно встановлені значення. При розробці ж нового коду не слід покладатися на те, що ці параметри включені, і вам варто розглянути можливість рефакторінга існуючого коду з метою позбутися від використання цих параметрів.
Параметри, які потрібно включити або змінити
У файлі php.ini є кілька параметрів, включення яких може трохи збільшити швидкість роботи ваших сценаріїв:
- output_buffering - переконайтеся, що цей параметр включений, так як завдяки йому дані будуть віддаватися браузеру великими фрагментами, а не при виконанні кожної інструкції echo або print. В іншому випадку час відгуку може бути істотно більше.
- variables_order - ця директива визначає порядок розбору змінних EGPCS- (Environment, Get, Post, Cookie і Server) вхідного запиту. Якщо ви не використовуєте суперглобальні змінні (наприклад, змінні середовища), ви можете, нічим не ризикуючи, їх прибрати, щоб не розбирати їх для кожного запиту, і отримати невеликий виграш продуктивності.
- date.timezone - ця директива, що з'явилася в PHP V5.1, дозволяє задати часовий пояс за умовчанням, який буде використовуватися у функціях класу DateTime. Якщо її не вказано у файлі php.ini, PHP зробить кілька системних запитів, щоб з'ясувати її значення, а в PHP V5.3 при обробці кожного запиту буде виводитися попередження.
Ці параметри можна назвати "низько висять фруктами", так як їх треба налаштувати в робочому середовищі в першу чергу. Також слід звернути увагу ще на одну річ, що стосується PHP. Це використання в вашому додатку інструкцій require () і include () (а також споріднених їм require_once () і include_once ()). Правильне використання цих інструкцій дозволяє запобігти непотрібні перевірки статусу файлів при кожному запиті, які можуть збільшувати час відгуку.
Управляємо інструкціями require () s і include () s
Виклики перевірки статусу файлів (тобто виклики до файлової системи, перевіряючі наявність того чи іншого файлу) можуть бути досить «дорогими» для продуктивності додатка. Найчастіше перевірки статусу файлів виконуються в інструкціях require () і include (), які використовуються для включення коду в ваш сценарій. Споріднені з ними виклики require_once () і include_once () можуть бути більш складними, так як в них потрібно не тільки переконатися в існуванні файлу, але і перевірити, що він не був включений раніше.
Отже, як щонайкраще з ними працювати? Є кілька нюансів, за допомогою яких можна прискорити роботу з ними.
- Використовуйте абсолютні шляхи для всіх викликів require () і include (). Завдяки цьому PHP буде точно знати, який саме файл ви хочете включити, і не потрібно буде шукати цей файл по всьому include_path.
- Зберігайте в include_path невелика кількість записів. Це допоможе в ситуаціях, коли складно надати абсолютний шлях для кожного виклику require () і include () (що часто зустрічається у великих старих додатках), так як PHP не доведеться шукати файл там, де його свідомо немає.
APC і Wincache також надають механізми кешування результатів перевірки статусу файлів, що виконуються PHP, що усуває необхідність повторних звернень до файлової системи. Вони найбільш ефективно працюють, коли імена підключаються файлів задаються статично, а не визначаються під час виконання, тому важливо намагатися по можливості задавати імена саме так.
Оптимізуємо базу даних
Оптимізація бази даних є досить складною темою, і нам просто не вистачить місця в цій статті, щоб повністю віддати їй належне. Однак є кілька кроків, виконання яких може допомогти прискорити роботу бази даних.
Помістіть базу даних на окрему машину
Запити до бази даних самі по собі можуть бути вельми «важкими», найчастіше під час виконання SELECT-запиту зі значною кількістю записів процесор буває зайнятий на всі 100 відсотків. Якщо і Web-сервер, і сервер бази даних конкурують за процесорний час на одній машині, запити можуть оброблятися досить повільно. Тому хорошим першим кроком є розміщення Web-сервера і сервера бази даних на різних машинах. Виділіть для сервера бази даних більш потужну машину (сервери бази даних люблять багато пам'яті і велика кількість процесорів).
Правильно проектують та індексує таблиці
Можливо, найбільші проблеми продуктивності бази даних викликані невдалою структурою бази даних і відсутністю індексів. У типовому Web-додатку найбільш часто виконуються є запити SELECT. Також саме ці запити є найбільш трудомісткими для сервера бази даних. Крім того, цей тип SQL-інструкцій є найбільш чутливим до правильного індексування структури бази даних, тому для оптимізації продуктивності варто дотримуватися наступних рекомендацій:
- У кожної таблиці повинен бути первинний ключ. Він надає сортування за замовчуванням, а також швидкий спосіб об'єднання даної таблиці з іншими таблицями.
- Всі зовнішні ключі таблиці (тобто ключі, що зв'язують запис в таблиці з будь-якої записом в іншій таблиці) повинні бути належним чином проіндексовані. Тут може допомогти те, що багато баз даних автоматично накладають на ці ключі обмеження, що гарантують, що запис з даними ключем дійсно існує в іншій таблиці.
- Намагайтеся обмежувати кількість стовпців в таблиці. Занадто велика кількість стовпців в таблиці може істотно збільшити час сканування при виконанні запитів. Крім цього, якщо в таблиці багато стовпців, які, як правило, не використовуються, то місце на диску буде займатися безліччю непотрібних значень NULL. Це справедливо і для полів змінного розміру, наприклад, text або blob, при використанні яких розмір таблиці може вирости набагато більше, ніж потрібно. В даному випадку слід розглянути можливість виділення додаткових стовпців в іншу таблицю, яку можна буде об'єднувати з головною таблицею по первинному ключу записів.
Аналізуємо виконуються на сервері запити
Найкращим способом поліпшення продуктивності бази даних є аналіз того, які запити виконуються на сервері, і як довго вони виконуються. Інструменти для цього аналізу є практично в кожній базі даних. В MySQL для знаходження проблемних запитів можна використовувати журнал повільних запитів. Для його використання задайте в файлі конфігурації MySQL параметром slow_query_log значення 1, параметру log_output значення FILE. Повільно виконуються запити будуть заноситися в файл журналу hostname-slow.log. У параметрі long_query_time можна задати в секундах порогове значення тривалості запиту, починаючи з якого запит буде вважатися "повільним". Я рекомендую для початку поставити значення 5 секунд, а потім поступово, в залежності від розміру ваших даних, скорочувати його до 1 секунди. Якщо відкрити цей файл, ви побачите в ньому детальну інформацію про запити, схожу на те, що показано в лістингу 1.
Лістинг 1. Журнал повільних запитів в MySQL
/ Usr / local / mysql / bin / mysqld, Version: 5.1.49-log, started with: Tcp port: 3306 Unix socket: /tmp/mysql.sock Time Id Command Argument # Time: 030207 15:03:33 # User @Host: user [user] @ localhost.localdomain [127.0.0.1] # Query_time: 13 Lock_time: 0 Rows_sent: 117 Rows_examined: 234 use sugarcrm; select * from accounts inner join leads on accounts.id = leads.account_id;
Для нас ключовим є значення Query_time, яке показує, як довго виконувався запит. Також представляють інтерес значення Rows_sent і Rows_examined, так як вони можуть вказати на ситуації, коли проглядається або повертається занадто багато рядків, можливо, через неправильно написаного запиту. Ви можете детально вивчити, як працює запит, додавши перед ним ключове слово EXPLAIN. У цьому випадку буде виведений не результат, а план запиту, як показано в лістингу 2.
Лістинг 2. Результати інструкції EXPLAIN в MySQL
mysql> explain select * from accounts inner join leads on accounts.id = leads.account_id; + ---- + ------------- + ---------- + -------- + ---------- ---------------- + --------- + --- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | + ---- + ------------- + ---------- + -------- + ---------- ---------------- + --------- + -------- | 1 | SIMPLE | leads | ALL | idx_leads_acct_del | NULL | NULL | NULL | 200 | | | 1 | SIMPLE | accounts | eq_ref | PRIMARY, idx_accnt_id_del | PRIMARY | 108 | sugarcrm.leads.account_id | 1 | | + ---- + ------------- + ---------- + -------- + ---------- ---------------- + --------- + --------- 2 rows in set (0.00 sec)
У керівництві по MySQL висновок інструкції EXPLAIN описується набагато докладніше (див. ресурси ), А тут ми згадаємо лише один важливий момент. Звертайте увагу на місця, де в стовпці 'type' знаходиться значення 'ALL', так як в таких випадках MySQL виконує повне сканування таблиці без використання ключів для пошуку. Це допоможе вам виявити місця, в яких додавання індексу істотно збільшить швидкість роботи.
Ефективно Кешуйте дані
Як ми бачили в попередньому розділі, бази даних легко можуть стати головним вузьким місцем продуктивності Web-додатки. Однак що робити, якщо дані, які ви запитуєте, чи не так часто змінюються? У такому випадку варто зберігати дані локально, а не витягувати їх з бази даних при кожному запиті.
У двох механізмах кешування опкодов, які ми розглянули раніше, - APC і Wincache - передбачені кошти і для цього. Вони дозволяють зберігати дані PHP безпосередньо в загальній пам'яті сегмента, звідки їх можна швидко витягти. У лістингу 3 наведено приклад того, як це робиться.
Лістинг 3. Приклад використання APC для кешування даних, отриманих з бази даних
<? Php function getListOfUsers () {$ list = apc_fetch ( 'getListOfUsers'); if (empty ($ list)) {$ conn = new PDO ( 'mysql: dbname = testdb; host = 127.0.0.1', 'dbuser', 'dbpass'); $ Sql = 'SELECT id, name FROM users ORDER BY name'; foreach ($ conn-> query ($ sql) as $ row) {$ list [] = $ row; } Apc_store ( 'getListOfUsers', $ list); } Return $ list; }
Кожен запит нам потрібно буде виконати тільки один раз. Після цього ми поміщаємо результат в призначений для користувача кеш APC під ключем getListOfUsers. Починаючи з цього моменту і до закінчення терміну дії кешу ви можете отримати цей результат безпосередньо з кешу, не виконуючи SQL-запит.
APC и Wincache є НЕ єдінімі засоби реализации призначення для користувача кешу; є такоже Популярні решение memcache и Redis, Які НЕ обов'язково повінні працювати на тій же машині, де працює Web-сервер. Це дає додаткову продуктивність і гнучкість, особливо якщо ваше Web-додаток «виросло» і працює на кількох Web-серверах.
Висновок
У цій статті ми розглянули п'ять простих способів настройки LAMP-додатки з метою підвищення продуктивності. Ми розглянули як прийоми, що стосуються PHP, - використання кешування опкодов і оптимізацію конфігурації PHP, - так і рекомендації щодо поліпшення архітектури бази даних і додаванню індексів. Також ми розглянули використання призначеного для користувача кеша (на прикладі APC), який дозволяє уникнути повторюваних запитів до бази даних у випадках, коли дані не дуже часто змінюються.
Ресурси для скачування
Схожі тими
- Five simple ways to tune your LAMP application : Оригінал статті (EN).
- " A PHP V5 migration guide ": Дізнайтеся, як мігрувати на версію V5 код, розроблений для PHP V4. (EN)
- Planet PHP - новинний сайт спільноти PHP-розробників. (EN)
- В керівництві по MySQL детально розповідається про виведення інструкції EXPLAIN. (EN)
- Alternative PHP Cache є, можливо, найпопулярнішим меахнізмом кешування опкодов для PHP. (EN)
- Wincache - це механізм кешування опкодов, найбільш активно розробляється командою IIS компанії Microsoft, призначений тільки для використання на Windows з Web-сервером IIS (Internet Information Services). (EN)
- eAccelerator - відгалуження одного з «рідних» механізмів кешування PHP, Turck MMCache. (EN)
- PHP.net -головний ресурс для PHP-розробників. (EN)
- перегляньте рекомендовані до прочитання матеріали по PHP . (EN)
- Слідкуйте за developerWorks в Твіттері . (EN)
- Чи використовуєте базу даних спільно з PHP? Зустрітися з Zend Core for IBM - готової, простий в установці середовищем розробки і виконання PHP, що підтримує IBM DB2 V9. (EN)
Підпішіть мене на ПОВІДОМЛЕННЯ до коментарів
Отже, як щонайкраще з ними працювати?Однак що робити, якщо дані, які ви запитуєте, чи не так часто змінюються?