Коли корисний кеш запитів

Не можна сказати, що кешування запитів автоматично виявляється більш ефективним, ніж його відсутність. На кешування йде час, тому виграш від кеша можна отримати, тільки якщо економія переважує витрати. А це залежить від завантаженості сервера.

Теоретично визначити, корисний кеш чи ні, можна, порівнявши обсяг роботи, який сервер повинен виконати з включеним і відключеним кешем. Якщо кеш відключений, то сервер виконує всі запити на читання і на запис, причому в першому випадку - ще генерує і повертає результати. Якщо кеш включений, то при обробці будь-якого запиту на читання необхідно спочатку перевірити кеш, а потім або повернути збережений результат, або (якщо його немає в кеші) виконати запит, згенерувати результуючий набір і відіслати його клієнту. При обробці будь-якого запиту на запис його слід спочатку виконати, а потім перевірити, чи потрібно оголосити недійсними якісь записи в кеші.

Хоча виглядає все це досить просто, точно передбачити виграш від використання кешу важко. Необхідно брати до уваги ще й зовнішні чинники. Наприклад, кеш запитів може скоротити час, необхідний для формування результату, але не час, потрібний для відправки його клієнту, а саме воно може виявитися домінуючим фактором.

Один з найпростіших способів зрозуміти, чи дає кеш виграш, - подивитися на коефіцієнт попадань в кеш. Він показує, скільки запитів було обслужено з кешу, а не виконано сервером з нуля. Коли сервер отримує команду SELECT, він збільшує одну з двох змінних стану: Qcache_hits або Com_select, в залежності від того, був запит кешуватися чи ні. Тому коефіцієнт попадань в кеш обчислюється за формулою Qcache_hits / (Qcache_hits + Com_select).

Будь-який запит SELECT, що не обслужений з кешу, називається непопаданням в кеш. Не потрапити в кеш можна з наступних причин.

• Запит не допускає кешування, оскільки або містить недетермінірованного конструкцію (наприклад, функцію CURRENT_DATE), або тому що результуючий набір занадто великий для збереженні гання в кеші. В обох випадках змінна Qcache_not_cached збільшується на одиницю.

• Сервер ще не бачив такий запит, тому не міг закешовану його результат.

• Результат запиту був раніше закешовану, але сервер видалив його. Таке може статися через брак пам'яті, через те, що хтось велів сервера видалити запит з кешу, або тому що запис була оголошена недійсною.

Якщо кількість невлучень в кеш велике, а кількість некешіру-ваних запитів дуже мало, то вірно одне з наступних тверджень.

• Кеш ще не «прогрілося», тобто сервер не встиг заповнити кеш результатами запитів.

• Сервер постійно бачить запити, які раніше не зустрічалися. Якщо кількість повторюваних запитів невелика, то таке може трапитися навіть, коли кеш «прогрілося».

• Занадто часто записи в кеші оголошуються недійсними.

Запис може стати недійсною через фрагментації, брак ресурсів або зміни даних. Якщо ви відвели під кеш досить пам'яті і правильно налаштували параметр query_cache_min_res_unit, то інвалідація здебільшого обумовлена ​​зміною збережених значень. Дізнатися, скільки запитів модифікували дані, дозволяють змінні стану Com_ * (Com_update, Com_delete і т. Д.), А скільки запитів було оголошено недійсними через брак пам'яті, - змінна Qcache_lowmem_prunes.

Має сенс розглядати витрати на інвалідацію окремо від коефіцієнта влучень. Припустимо, наприклад, що з однієї таблиці проводиться тільки читання, при цьому коефіцієнт попадання дорівнює 100%, а в іншій - тільки оновлення. Якщо обчислити коефіцієнт влучення по змінним стану, то він складе 100%. Але навіть в цьому випадку використання кеша може виявитися неефективним, оскільки уповільнює виконання запитів на оновлення. При обробці будь-якого запиту на оновлення доводиться перевіряти, чи не потрібно оголосити недійсними якісь кешированниє дані, але оскільки відповідь незмінно буде «ні», то вся ця робота пророблена даремно. Такого роду проблему можна і не помітити, а то й проаналізувати спільно кількість некешіруемих запитів і коефіцієнт попадання.

Сервер, для якого суміш операцій записи і кешувального читання з одних і тих же таблиць збалансована, теж не завжди виграє від наявності кеша запитів. Будь-яка операція запису робить запити в кеші недійсними, тоді як будь-яка операція читання вставляє в кеш новий запит. А виграш можна отримати тільки, якщо ці запити потім обслуговуються з кеша.

Якщо закешовану результат стає недійсним до того, як сервер знову отримує ту ж саму команду SELECT, то вся робота по збереженню була марною тратою часу і пам'яті. Щоб зрозуміти, чи має місце така ситуація, порівняйте значення змінних Com_select і Qcache_inserts. Якщо майже всі команди SELECT не потрапляють в кеш (при цьому збільшується значення Com_select), після чого їх результуючі набори кешуються, то Qcache_inserts буде мало відрізнятися від Com_select. А хотілося б, щоб значення Qcache_inserts було істотно менше Com_select, по крайней мере, після «прогріву» кеша.

Для кожної програми існує кінцевий потенційний розмір кешу, навіть при відсутності операцій записи. Потенційний розмір - це обсяг пам'яті, необхідний для збереження всіх Кешована запитів, які може виконати додаток. Теоретично для більшості випадків цей розмір дуже великий. Але на практиці у багатьох додатків він набагато менше, ніж можна було б очікувати, через те, що більшість записів в кеші стають недійсними. Навіть якщо виділити для кеша запитів дуже багато пам'яті, він ніколи не заповниться більше, ніж на потенційний розмір кеша.

Необхідно стежити за тим, яка частка виділеної для кешу пам'яті реально використовується. Якщо використовується не вся пам'ять, зменшіть розмір кешу, якщо через брак пам'яті часто відбувається витіснення, - збільште його. Втім, надмірна розмір кешу - це не так страшно; через те, що виділено трохи більше або трохи менше пам'яті, ніж реально потрібно, продуктивність сильно не постраждає. Проблема виникає, коли не використовується дуже багато пам'яті або запити витісняються з кешу настільки часто, що все кешування приносить тільки збитки.

Необхідно також співставляти розмір кеша запитів з іншими серверними кешами, наприклад пулом буферів InnoDB або кешем ключів MyISAM. Неможливо запропонувати коефіцієнт на всі випадки життя або яку-небудь просту формулу, оскільки відповідний баланс залежить від конкретного додатка.

Схожі статті