Пошук та виправлення повільних запитів до бази даних WordPress, все про WordPress
Повільні SQL-запити можуть негативно вплинути на продуктивності WordPress-сайту. Іноді повільні запити – це результат погано сформованого SQL-коду, який має бути реалізований дещо іншим шляхом. І в деяких ситуаціях повільні запити спочатку були швидкими – але зі зростанням віку сайту запити ставали все повільнішими і повільнішими, і вже починали відставати від бази даних, що розширюється.
Незалежно від того, як ваш SQL-код став повільним, давайте поглянемо на деякі шляхи пошуку та усунення проблемних запитів у WordPress.
Пошук повільних запитів
Пошук джерела повільних запитів включає два кроки:
- Визначаємо які запити насправді повільні.
- Шукаємо код, який генерує та виконує їх.
Давайте розглянемо два плагіни та одне SaaS-рішення, які допоможуть нам знайти повільні запити.
Query Monitor
Query Monitor – плагін, що виводить різну інформацію про поточну сторінку. На додаток до численних даних про внутрішні механізми WordPress, плагін виводить детальну статистику за такими пунктами:
- Скільки запитів відбулося за цим викликом
- Які запити на сторінці зайняли найбільше часу
- Які функції виконувались найдовше у SQL-запитах
- Які запити йшли від плагінів, тим і ядра WordPress

Query Monitor виділяє повільні запити за допомогою страшного червоного тексту, який спрощує виявлення проблемного SQL:

Debug Bar
Ще один чудовий інструмент для пошуку повільного SQL - це старий добрий плагін Debug Bar. Debug Bar виводить інформацію провнутрішніх механізмах WordPress, коли ви завантажуєте сторінку з такими даними, як:
- Параметри WP_Query
- Інформація дзвінка (включаючи відповідність правил перезапису)
- SQL-запити, що генеруються поточною сторінкою
Щоб активувати третій пункт у Debug Bar (SQL відстеження), переконайтеся, що SAVEQUERIES включена на вашому сайті – зазвичай це робиться у файлі wp-config.php:
Застереження: SAVEQUERIES відбивається на продуктивності вашого сайту, і, швидше за все, не має використовуватися на робочому сайті. Використовуйте її тільки на сайті, що розробляється.
Пошук повільного SQL у Debug Bar не такий простий. Наприклад, плагін немає сортованих таблиць і підсвічує повільні запити. Debug Bar забезпечує трасування функцій, що дозволяє виявити джерело запиту.

Тут наведено список файлів, що завантажуються і функцій, які призводять до виконання запиту. В основному вам буде цікавий останній запис у списку; саме там виконується найповільніший запит і саме з нього вам потрібно буде розпочати свій пошук. Також зручним є наявність контексту кожної окремої функції.
NewRelic
NewRelic – це сервіс, який вимірює та відстежує довільність вашої веб-програми, включаючи WordPress. Сервіс пропонує багато різної інформації про продуктивність вашого сайту. Дуже легко загубитися в даних, які пропонує NewRelic, починаючи з детального виконання коду і закінчуючи покроковими звітами SQL-запитів.

Є дві великі відмінності між NewRelic і плагінами, згаданими вище:
- NewRelic відображає більш детальну інформацію про продуктивність вашого PHP, аж до мілісекунд, витрачених на виконання кожноїфункції.
- NewRelic відстежує кожен запит до вашого сайту у фоновому режимі, тобто. Ви можете проаналізувати інформацію пізніше для пошуку повільного SQL. Плагіни виводять інформацію лише для поточної сторінки.
Варто зазначити, що NewRelic має безкоштовний план, який дозволяє вивести загальну інформацію про продуктивність вашого сайту, проте для отримання всіх важливих деталей вам доведеться перейти на платний тариф. Саме в цьому плані ви зможете відстежувати окремі запити та знаходити повільний SQL.
Виявлення повільних запитів за допомогою EXPLAIN
Донедавна ми розглядали інструменти для пошуку повільних запитів. Давайте розглянемо, чому ці запити стають повільними.
У цьому ми допоможе MySQL ключ EXPLAIN. Він дозволить зрозуміти, що сталося. Додавання EXPLAIN на початок запиту покаже, як MySQL виконує запит. У разі більш складних запитів EXPLAIN допоможе виявити повільні ділянки у ваших SQL – наприклад, повільні підзапити чи неефективні процеси.
Наприклад, якщо ви маєте запит наступного виду:
Ви можете додати до нього EXPLAIN, просто виконавши таке:
Ось як виглядає висновок EXPLAIN у phpMyAdmin:
Я не зовсім розумію, як працюють внутрішні механізми MySQL, але запуск EXPLAIN для запитів дає мені розуміння того, як MySQL виконує мій SQL-запит. Чи запитує індекс? Чи він сканує всю таблицю? Навіть для простих запитів EXPLAIN забезпечує деяку інформацію, що дозволяє зрозуміти, як усе працює.
Ви можете запустити EXPLAIN або з командного рядка MySQL, або через ваш переважний інструмент MySQL.
Виправлення повільних запитів
Тепер, коли ми знаємо, що наш запит є повільним, таEXPLAIN показав нам, чому запит є повільним, настав час подивитися, як ми можемо виправити ці проблеми.
Варіант 1. Зміна запиту.
На сайті CSS-Tricks ми маємо запит, який виконується дуже повільно – цей запит є частиною мета-панелі Custom Fields. Ось сам SQL:
Цей фрагмент коду містить SQL, що дозволяє отримати список meta_keys з таблиці wp_postmeta. meta_keys, що цікавлять нас, не повинні починатися з підкреслення «_». Оператор GROUP BY означає, що кожен результат є унікальним.
Виконавши цей запит 5 разів, ми отримаємо такі дані:
Чи могли б ми написати інший запит, щоб отримати той самий результат? Нам необхідно вибрати унікальні meta_keys. Синонім до слова «unique» (унікальний) – distinct, і, як виявилося, у SQL є такий оператор!
Використовуючи оператор DISTINCT, ми можемо зробити таке:
Виконання нашого зміненого запиту кілька разів дає такі результати:
Це порівняння демонструє суттєве покращення!
Варіант 2. Додавання індексу.
Коли ви виконуєте запит SQL до стандартної таблиці MySQL, MySQL сканує всю таблицю, щоб визначити, які рядки відповідають цьому запиту. Якщо ваша таблиця дуже велика, то сканування займе досить багато часу.
В цьому випадку добре допомагають індекси MySQL. Індекси беруть дані з таблиці і мають у своєму розпорядженні їх так, щоб ці дані було найпростіше знайти. Структуруючи дані таким чином, індекси допомагають позбавитися тривалого сканування, яке робить MySQL для кожного запиту.
Індекси можуть бути додані до окремих стовпців або групи стовпців. Синтаксис виглядає так:
З індексом для meta_keyвихідний SQL-запит буде виконуватися так:
Застереження щодо використання індексів: щоразу, коли INSERT створює рядок, чи UPDATE використовується для індексованої сторінки, індекс обчислюється заново, що досить тривалої операцією. Індекси прискорюють зчитування з таблиці, але уповільнюють внесення даних до неї. Вдало розташований індекс може значно прискорити ваші запити, проте не варто скрізь їх розставляти, не вивчивши загальний вплив індексів на базу даних.
Варіант 3. Кешування результатів запиту
Ми знаємо, що ми маємо повільні запити. Замість того, щоб їх переписувати, ми можемо просто зберегти результати запиту. Таким чином, ми обмежимо частоту виконання запиту, а також отримаємо швидку відповідь.
Щоб кешувати запит, нам знадобиться WordPress Transients API. Transients використовуються для зберігання результатів складних операцій, таких як:
- Запити до зовнішніх сайтів (наприклад, отримання останніх записів Facebook)
- Повільні блоки обробки (наприклад, пошук довгих рядків за допомогою регулярних виразів)
- Повільні запити до бази даних
Зберігання результатів запиту в transients буде виглядати так:
Це означає, що запит буде виконуватися лише один раз на годину або щось близько. Звідси випливає одна з основних застережень щодо використання transient: будьте обережні при використанні transient з даними, які часто змінюються.
Якщо у вас є запит, результати якого змінюються не так часто, використання transients – чудовий спосіб обійти часте звернення до бази даних.
Вибір підходу
Ми розглянули три варіанти, і крім них є ще приблизно 17 способів розв'язанняпроблеми із повільними запитами. Який підхід найкраще вибрати?
Коли я працюю з чужим кодом, я волію орієнтуватися на принцип програмістів: «Вибирай найпростіше рішення, яке може працювати».
Перший варіант (переписування запиту) дозволив отримати чудові результати, проте як бути, якщо переписаний запит не завжди видає ті самі результати? Ми можемо несвідомо порушити код шляхом заміни запитів.
Другий варіант (додавання індексу) не завжди можливий, що залежить від таблиці та стовпців, які використовуються запитом. У випадку з базовими таблицями WordPress вам потрібно буде подумати про можливі побічні ефекти індексації:
- Чи підтримує оновлення ядра додаткові індекси?
- Чи не сповільнить додавання індексу інші запити, такі як INSERT та UPDATE?
Третій варіант (кешування результатів через transients) має мінімальний вплив – ми не змінюємо вихідний запит і нам не потрібно змінювати структуру бази даних.
Більшість часу я використовую третій варіант. У вашому випадку ви можете вибрати інший варіант, який залежить від запиту, який ви хочете виправити, а також від проблем SQL. Одного рішення, яке підійшло б у всіх ситуаціях, немає, тому пробуйте різні варіанти.