Чому балакучий SQL-застосунок повзе через VPN і що варто об’єднувати в пакети
Екран, що надсилає сто залежних запитів, платить за круговий шлях сто разів. Порахуйте очікування, об’єднайте незалежні, потім перенесіть виконання.
Форма, яка в локальній мережі відкривається менш ніж за секунду, через VPN займає п’ять секунд, тоді як копіювання файлу тим самим каналом іде на повній швидкості. Різниця не в пропускній здатності. Форма чекає на послідовність відповідей і на кожному кроці платить повний круговий шлях, а копіювання файлу безперервно тримає байти в польоті. Порахуйте ці очікування, перш ніж торкатися лінії доступу.
Симптом це екран, а не запит
Кожен запит на цьому екрані може бути швидким, а екран усе одно може бути повільним, бо підсумок це сума очікувань, а не сума часів виконання. Оператор, що виконується за дві мілісекунди, все одно коштує цілого кругового шляху, коли клієнт має отримати результат перед надсиланням наступного. На маршруті із затримкою сорок мілісекунд сто залежних викликів складаються приблизно в чотири секунди, перш ніж почнеться будь-яка робота малювання. Ця арифметика це модель очікування, а не вимірювання вашого каналу.
Ось чому тест швидкості виглядає невинно. Масове передавання вимірює пропускну здатність, балакуча форма вимірює затримку, і VPN може бути чудовим в одному й залишатися звичайним в іншому. Тому діагностувати екран означає вимірювати екран, а не канал.
Запишіть час від початку до кінця однієї дії користувача, перш ніж щось змінювати. Лише це число може сказати, чи спрацювала пізніша правка.
Порахуйте послідовні очікування в одній дії користувача
Інструментуйте клієнт замість здогадок. У psql \timing on друкує минулий час кожного оператора, а EXPLAIN (ANALYZE, BUFFERS) показує, скільки з цього часу сервер справді витратив на роботу.
Різниця між цими двома числами це ваші мережеві та клієнтські накладні витрати. Якщо оператор виконується за дві мілісекунди, а клієнт фіксує шістдесят, решта п’ятдесят вісім це дорога й локальна обробка, і жоден індекс їх не прибере. Повторіть це порівняння для кожного оператора, який надсилає екран, і додавайте різниці, а не часи виконання.
Запишіть результат як кількість послідовних очікувань. Саме цю величину можуть зменшити наступні два розділи, і це число, про яке можна сперечатися з доказами.
Об’єднуйте незалежні виклики, залишайте залежні
Два оператори, які не читають результату один одного, можуть їхати разом і бути зібрані один раз, що перетворює два очікування на одне. Два оператори, де другому потрібне значення першого, так не можуть, бо залежність реальна і об’єднання змінило б те, що робить програма. Розкладіть виклики на ці дві купи, перш ніж щось переписувати, і розмір кожної купи скаже, що можливо.
Робота на множинах усуває очікування ґрунтовніше, ніж об’єднання в пакети. Один запит, що повертає рядки, які цикл тягнув по одному, усуває і цикл, і кругові шляхи. Шукайте спершу цикл, бо зазвичай це більший виграш і простіша для перевірки правка.
Пакет усе одно має зберегти обробку помилок і межі транзакцій. Склеювання незв’язаних операторів в один рядок не є безпечною оптимізацією, а пакет, що ховає невдалий оператор за успішним надсиланням, гірший за зекономлені очікування.
Використовуйте з’єднання повторно, перш ніж купувати смугу пропускання
Нове з’єднання коштує розв’язання імен, рукостискання TCP, узгодження TLS і автентифікації, і на маршруті з високою затримкою кожне з цього це ще один круговий шлях до запуску першого запиту. Пули з’єднань існують, щоб платити цю ціну один раз на процес, а не один раз на виклик.
У ADO.NET закриття або dispose з’єднання з пулу повертає його для повторного використання, а не відкриває нове фізичне, тому шаблон, схожий на витік, часто є правильним використанням. Перевірте, чи пул справді використовується, замість припущення: логуйте створення фізичних з’єднань або стежте за кількістю сесій на сервері, поки екран працює. Настанови щодо продуктивності SQL кажуть те саме про скорочення кругових шляхів і об’єднання частих ad hoc викликів, із прикладами для конкретних служб, які слід перенести на ваше розгортання.
Пулінг прибирає витрати на налаштування і залишає послідовні очікування запитів недоторканими. Це передумова чистого вимірювання, а не самостійне виправлення.
Зважте перенесення виконання ближче до даних
Запуск застосунку близько до бази даних замінює багато віддалених обмінів із базою однією віддаленою сесією відображення. Для балакучого навантаження це може бути великою зміною, і це операційна зміна такою ж мірою, як і зміна продуктивності: керування сесіями, контроль доступу, розгортання програмного забезпечення та досвід користувача рухаються разом із застосунком.
Виміряйте фактичний інтерфейс і дані, які він передає, перш ніж припускати, що якийсь напрям швидший. Сесія віддаленого робочого столу передає пікселі, і екран із щільною графікою може працювати гірше тим самим маршрутом, ніж запити, які він замінив, особливо коли клієнт безперервно перемальовує.
Потім повторіть початкову дію і порівняйте три числа: послідовні очікування, обсяг результатів і час завершення від початку до кінця. Покращення, яке змінює вимірюване завдання користувача, зберігаючи коректність даних і політику доступу, це те, яке варто залишити.